# Maximum sum of values of N items in 0-1 Knapsack by reducing weight of at most K items in half

• Difficulty Level : Expert
• Last Updated : 01 Dec, 2022

Given weights and values of N items and the capacity W of the knapsack. Also given that the weight of at most K items can be changed to half of its original weight. The task is to find the maximum sum of values of N items that can be obtained such that the sum of weights of items in knapsack does not exceed the given capacity W.

Examples:

Input: W = 4, K = 1, value = [17, 20, 10, 15], weight = [4, 2, 7, 5]
Output: 37
Explanation: Change the weight of at most K items to half of the weight in a optimal way to get maximum value. Decrease the weight of first item to half and add second item weight the resultant sum of value is 37 which is maximum

Input: W = 8, K = 2, value = [17, 20, 10, 15], weight = [4, 2, 7, 5]
Output: 52
Explanation: Change the weight of the last item and first item and the add the weight the of the 2nd item, The total sum value of item will be 52.

Approach: Given problem is the variation of the 0 1 knapsack  problem. Flag indicates number of items whose weight has been reduced to half. At every recursive call maximum of following cases is calculated and returned:

• Base case: If the index exceeds the length of values then return zero
• If flag is equal to K, maximum of 2 cases is considered:
• Include item with full weight if item’s weight does not exceed remaining weight
• Skip the item
• If flag is less than K, maximum of 3 cases is considered:
• Include item with full weight if item’s weight does not exceed remaining weight
• Include item with half weight if item’s  half weight does not exceed remaining weight
• Skip the item

## C++

 `// C++ Program to implement` `// the above approach` `#include ` `using` `namespace` `std;` `// Function to find the maximum  value`   `int` `maximum(``int` `value[], ``int` `weight[], ``int` `weight1,` `            ``int` `flag, ``int` `K, ``int` `index, ``int` `val_len)` `{`   `    ``// base condition` `    ``if` `(index >= val_len) {`   `        ``return` `0;` `    ``}`   `    ``// K elements already reduced` `    ``// to half of their weight` `    ``if` `(flag == K) {`   `        ``// Dont include item` `        ``int` `skip = maximum(value, weight, weight1, flag, K,` `                           ``index + 1, val_len);`   `        ``int` `full = 0;`   `        ``// If weight of the item is` `        ``// less than  or equal to the` `        ``// remaining weight then include` `        ``// the item` `        ``if` `(weight[index] <= weight1) {`   `            ``full = value[index]` `                   ``+ maximum(value, weight,` `                             ``weight1 - weight[index], flag,` `                             ``K, index + 1, val_len);` `        ``}`   `        ``// Return the maximum  of` `        ``// both cases` `        ``return` `max(full, skip);` `    ``}`   `    ``// If the weight reduction to half` `    ``// is possible` `    ``else` `{`   `        ``// Skip the item` `        ``int` `skip = maximum(value, weight, weight1, flag, K,` `                           ``index + 1, val_len);`   `        ``int` `full = 0;` `        ``int` `half = 0;`   `        ``// Include item with full weight` `        ``// if weight of the item is less` `        ``// than the remaining weight` `        ``if` `(weight[index] <= weight1) {`   `            ``full = value[index]` `                   ``+ maximum(value, weight,` `                             ``weight1 - weight[index], flag,` `                             ``K, index + 1, val_len);` `        ``}`   `        ``// Include item with half weight` `        ``// if half weight of the item is` `        ``// less than the remaining weight` `        ``if` `(weight[index] / 2 <= weight1) {`   `            ``half = value[index]` `                   ``+ maximum(value, weight,` `                             ``weight1 - weight[index] / 2,` `                             ``flag + 1, K, index + 1,` `                             ``val_len);` `        ``}`   `        ``// Return the maximum of all 3 cases` `        ``return` `max(full, max(skip, half));` `    ``}` `}` `int` `main()` `{`   `    ``int` `value[] = { 17, 20, 10, 15 };` `    ``int` `weight[] = { 4, 2, 7, 5 };` `    ``int` `K = 1;` `    ``int` `W = 4;` `    ``int` `val_len = ``sizeof``(value) / ``sizeof``(value[0]);` `    ``cout << (maximum(value, weight, W, 0, K, 0, val_len));`   `    ``return` `0;` `}`   `// This code is contributed by Potta Lokesh`

## Java

 `// Java implementation for the above approach` `import` `java.io.*;` `import` `java.util.*;`   `class` `GFG {`   `    ``// Function to find the maximum  value` `    ``static` `int` `maximum(``int` `value[], ``int` `weight[],` `                       ``int` `weight1, ``int` `flag, ``int` `K,` `                       ``int` `index)` `    ``{`   `        ``// base condition` `        ``if` `(index >= value.length) {`   `            ``return` `0``;` `        ``}`   `        ``// K elements already reduced` `        ``// to half of their weight` `        ``if` `(flag == K) {`   `            ``// Dont include item` `            ``int` `skip = maximum(value, weight, weight1, flag,` `                               ``K, index + ``1``);`   `            ``int` `full = ``0``;`   `            ``// If weight of the item is` `            ``// less than  or equal to the` `            ``// remaining weight then include` `            ``// the item` `            ``if` `(weight[index] <= weight1) {`   `                ``full = value[index]` `                       ``+ maximum(value, weight,` `                                 ``weight1 - weight[index],` `                                 ``flag, K, index + ``1``);` `            ``}`   `            ``// Return the maximum  of` `            ``// both cases` `            ``return` `Math.max(full, skip);` `        ``}`   `        ``// If the weight reduction to half` `        ``// is possible` `        ``else` `{`   `            ``// Skip the item` `            ``int` `skip = maximum(value, weight, weight1, flag,` `                               ``K, index + ``1``);`   `            ``int` `full = ``0``;` `            ``int` `half = ``0``;`   `            ``// Include item with full weight` `            ``// if weight of the item is less` `            ``// than the remaining weight` `            ``if` `(weight[index] <= weight1) {`   `                ``full = value[index]` `                       ``+ maximum(value, weight,` `                                 ``weight1 - weight[index],` `                                 ``flag, K, index + ``1``);` `            ``}`   `            ``// Include item with half weight` `            ``// if half weight of the item is` `            ``// less than the remaining weight` `            ``if` `(weight[index] / ``2` `<= weight1) {`   `                ``half` `                    ``= value[index]` `                      ``+ maximum(value, weight,` `                                ``weight1 - weight[index] / ``2``,` `                                ``flag, K, index + ``1``);` `            ``}`   `            ``// Return the maximum of all 3 cases` `            ``return` `Math.max(full, Math.max(skip, half));` `        ``}` `    ``}`   `    ``public` `static` `void` `main(String[] args) ``throws` `Exception` `    ``{`   `        ``int` `value[] = { ``17``, ``20``, ``10``, ``15` `};` `        ``int` `weight[] = { ``4``, ``2``, ``7``, ``5` `};` `        ``int` `K = ``1``;` `        ``int` `W = ``4``;` `        ``System.out.println(` `            ``maximum(value, weight, W, ``0``, K, ``0``));` `    ``}` `}`

## Python3

 `# Python program for the above approach`   `# Function to find the maximum  value`     `def` `maximum(value,` `            ``weight, weight1,` `            ``flag, K, index, val_len):`   `    ``# base condition` `    ``if` `(index >``=` `val_len):`   `        ``return` `0`   `    ``# K elements already reduced` `    ``# to half of their weight` `    ``if` `(flag ``=``=` `K):`   `        ``# Dont include item` `        ``skip ``=` `maximum(value,` `                       ``weight, weight1,` `                       ``flag, K, index ``+` `1``, val_len)`   `        ``full ``=` `0`   `        ``# If weight of the item is` `        ``# less than  or equal to the` `        ``# remaining weight then include` `        ``# the item` `        ``if` `(weight[index] <``=` `weight1):`   `            ``full ``=` `value[index] ``+` `maximum(` `                ``value, weight,` `                ``weight1 ``-` `weight[index], flag,` `                ``K, index ``+` `1``, val_len)`   `        ``# Return the maximum  of` `        ``# both cases` `        ``return` `max``(full, skip)`   `    ``# If the weight reduction to half` `    ``# is possible` `    ``else``:`   `        ``# Skip the item` `        ``skip ``=` `maximum(` `            ``value, weight,` `            ``weight1, flag,` `            ``K, index ``+` `1``, val_len)`   `        ``full ``=` `0` `        ``half ``=` `0`   `        ``# Include item with full weight` `        ``# if weight of the item is less` `        ``# than the remaining weight` `        ``if` `(weight[index] <``=` `weight1):`   `            ``full ``=` `value[index] ``+` `maximum(` `                ``value, weight,` `                ``weight1 ``-` `weight[index],` `                ``flag, K, index ``+` `1``, val_len)`   `        ``# Include item with half weight` `        ``# if half weight of the item is` `        ``# less than the remaining weight` `        ``if` `(weight[index] ``/` `2` `<``=` `weight1):`   `            ``half ``=` `value[index] ``+` `maximum(` `                ``value, weight,` `                ``weight1 ``-` `weight[index] ``/` `2``,` `                ``flag, K, index ``+` `1``, val_len)`   `        ``# Return the maximum of all 3 cases` `        ``return` `max``(full,` `                   ``max``(skip, half))`     `# Driver Code`   `value ``=` `[``17``, ``20``, ``10``, ``15``]` `weight ``=` `[``4``, ``2``, ``7``, ``5``]` `K ``=` `1` `W ``=` `4` `val_len ``=` `len``(value)` `print``(maximum(value, weight, W,` `              ``0``, K, ``0``, val_len))`   `# This code is contributed by sanjoy_62.`

## C#

 `// C# implementation for the above approach` `using` `System;`   `public` `class` `GFG {`   `    ``// Function to find the maximum  value` `    ``static` `int` `maximum(``int``[] value, ``int``[] weight,` `                       ``int` `weight1, ``int` `flag, ``int` `K,` `                       ``int` `index)` `    ``{`   `        ``// base condition` `        ``if` `(index >= value.Length) {`   `            ``return` `0;` `        ``}`   `        ``// K elements already reduced` `        ``// to half of their weight` `        ``if` `(flag == K) {`   `            ``// Dont include item` `            ``int` `skip = maximum(value, weight, weight1, flag,` `                               ``K, index + 1);`   `            ``int` `full = 0;`   `            ``// If weight of the item is` `            ``// less than  or equal to the` `            ``// remaining weight then include` `            ``// the item` `            ``if` `(weight[index] <= weight1) {`   `                ``full = value[index]` `                       ``+ maximum(value, weight,` `                                 ``weight1 - weight[index],` `                                 ``flag, K, index + 1);` `            ``}`   `            ``// Return the maximum  of` `            ``// both cases` `            ``return` `Math.Max(full, skip);` `        ``}`   `        ``// If the weight reduction to half` `        ``// is possible` `        ``else` `{`   `            ``// Skip the item` `            ``int` `skip = maximum(value, weight, weight1, flag,` `                               ``K, index + 1);`   `            ``int` `full = 0;` `            ``int` `half = 0;`   `            ``// Include item with full weight` `            ``// if weight of the item is less` `            ``// than the remaining weight` `            ``if` `(weight[index] <= weight1) {`   `                ``full = value[index]` `                       ``+ maximum(value, weight,` `                                 ``weight1 - weight[index],` `                                 ``flag, K, index + 1);` `            ``}`   `            ``// Include item with half weight` `            ``// if half weight of the item is` `            ``// less than the remaining weight` `            ``if` `(weight[index] / 2 <= weight1) {`   `                ``half` `                    ``= value[index]` `                      ``+ maximum(value, weight,` `                                ``weight1 - weight[index] / 2,` `                                ``flag, K, index + 1);` `            ``}`   `            ``// Return the maximum of all 3 cases` `            ``return` `Math.Max(full, Math.Max(skip, half));` `        ``}` `    ``}`   `    ``// Driver code` `    ``public` `static` `void` `Main(String[] args)` `    ``{`   `        ``int``[] value = { 17, 20, 10, 15 };` `        ``int``[] weight = { 4, 2, 7, 5 };` `        ``int` `K = 1;` `        ``int` `W = 4;` `        ``Console.WriteLine(` `            ``maximum(value, weight, W, 0, K, 0));` `    ``}` `}`   `// This code is contributed by shikhasingrajput`

## Javascript

 ``

Output

`37`

Time Complexity: O(3^N)
Auxiliary Space: O(N)

Given problem is the variation of the 0-1 knapsack  problem. In traditional 0-1 Knapsack problem, we only have to choices: skip the i-th item or take it.
However, in this case we will have 3 choices as mentioned in the recursive approach.

Efficient Approach (Dynamic Programming):

In Dynamic programming, we will work considering the same cases as above. We shall consider a 3D DP table where the state DP[i][j][k] will denote the maximum value we can obtain if we are considering values from 1 to i-th, weight of the knapsack is j and we can half the weight of at most k values. Basically, we are adding one extra state, the number of weights that can be halved in a traditional 2-D 01 knapsack DP matrix.

Now, three possibilities can take place:

• Include item with full weight if the itemâ€™s weight does not exceed the remaining weight
• Include the item with half weight if the itemâ€™s  half weight does not exceed the remaining weight
• Skip the item

Now we have to take the maximum of these three possibilities. If we do not take the i-th weight then dp[i][j][k] would remain equal to dp[i – 1][j][k], just llike traditional knapsack. If we include item with half weight then dp[i][j][k] would be equal to dp[i – 1][j – wt[i] / 2][k – 1] + val[i] as after including i-th value our remaining knapsack capacity would be j – wt[i] / 2 and our number of half operations would increase by 1. Similarly, if we include item with full weight then dp[i][j][k] would be equal to dp[i – 1][j – wt[i]][k] + val[i] as knapsack capacity in this case would reduce to j – wt[i].
We simply take the maximum of all three choices.

Below is the code implementation of above approach:

## C++

 `#include ` `#include ` `#include ` `using` `namespace` `std;` `int` `getMaximumNutrition(``int` `W, vector<``int``> value, vector<``int``> weight, ``int` `x) {` `    ``int` `n=value.size();` `    ``int` `dp[n + 1][W + 1][x + 1];` `  ``/*` `  ``dp[i][j][k] denotes the maximum value that we can obtain if we are considering first i ` `  ``elements of array, our capacity is j and we can use only k half operations` `  ``*/` `    ``memset``(dp, 0, ``sizeof``(dp));` `    ``for``(``int` `i = 1;i <= n; i++)` `    ``{` `        ``for``(``int` `j = 1;j <= W; j++)` `        ``{` `            ``int` `lim = x;` `            ``if``(lim > i)` `            ``{` `                ``lim = i;` `            ``}` `            ``for``(``int` `k = 0;k <= lim; k++)` `            ``{` `                ``dp[i][j][k] = max(dp[i - 1][j][k], dp[i][j][k]);``//skip` `                ``int` `val = j - (weight[i - 1] / 2);` `                ``if``(val >= 0 && k > 0)``//ensure that j-weight[i-1]/2 and k-1 don't become -ve` `                ``{` `                    ``dp[i][j][k] = max(dp[i - 1][val][k - 1]+value[i - 1], dp[i][j][k]);` `                  ``//take item applying half operation` `                ``}` `                ``val = j - weight[i - 1];` `                ``if``(val >= 0)``//ensure that j-weight[i-1] doesn't become -ve` `                ``{` `                    ``dp[i][j][k] = max(dp[i - 1][val][k] + value[i - 1], dp[i][j][k]);` `                  ``//take item without applying half operation` `                ``}` `            ``}` `        ``}` `    ``}` `    ``return` `dp[n][W][x];` `}` `int` `main() {` `    ``vector<``int``> value = {17, 20, 10, 15};` `    ``vector<``int``> weight = {4, 2, 7, 5};` `    ``int` `x = 1;` `    ``int` `W = 4;` `    ``cout << getMaximumNutrition(W, value, weight, x);` `    ``return` `0;` `}`

## C#

 `using` `System;` `class` `GFG {` `  ``static` `int` `getMaximumNutrition(``int` `W, ``int``[] value,` `                                 ``int``[] weight, ``int` `x)` `  ``{` `    ``int` `n = value.Length;` `    ``int``[, , ] dp = ``new` `int``[n + 1, W + 1, x + 1];` `    ``/*` `        ``dp[i][j][k] denotes the maximum value that we can` `        ``obtain if we are considering first i elements of` `        ``array, our capacity is j and we can use only k half` `        ``operations` `        ``*/`   `    ``for` `(``int` `i = 1; i <= n; i++) {` `      ``for` `(``int` `j = 1; j <= W; j++) {` `        ``int` `lim = x;` `        ``if` `(lim > i) {` `          ``lim = i;` `        ``}` `        ``for` `(``int` `k = 0; k <= lim; k++) {` `          ``dp[i, j, k]` `            ``= Math.Max(dp[i - 1, j, k],` `                       ``dp[i, j, k]); ``// skip` `          ``int` `val = j - (weight[i - 1] / 2);` `          ``if` `(val >= 0` `              ``&& k > 0) ``// ensure that` `            ``// j-weight[i-1]/2 and k-1` `            ``// don't become -ve` `          ``{` `            ``dp[i, j, k]` `              ``= Math.Max(dp[i - 1, val, k - 1]` `                         ``+ value[i - 1],` `                         ``dp[i, j, k]);` `            ``// take item applying half operation` `          ``}` `          ``val = j - weight[i - 1];` `          ``if` `(val` `              ``>= 0) ``// ensure that j-weight[i-1]` `            ``// doesn't become -ve` `          ``{` `            ``dp[i, j, k]` `              ``= Math.Max(dp[i - 1, val, k]` `                         ``+ value[i - 1],` `                         ``dp[i, j, k]);` `            ``// take item without applying half` `            ``// operation` `          ``}` `        ``}` `      ``}` `    ``}` `    ``return` `dp[n, W, x];` `  ``}` `  ``static` `void` `Main()` `  ``{` `    ``int``[] val = { 17, 20, 10, 15 };` `    ``int``[] weight = { 4, 2, 7, 5 };` `    ``int` `x = 1;` `    ``int` `W = 4;` `    ``Console.Write(` `      ``getMaximumNutrition(W, val, weight, x));` `  ``}` `}`   `// This code is contributed by garg28harsh.`

Output

`37`

Time Complexity: O(n*W*K)
Auxiliary Space: O(n*W*K)

Note that space complexity can be further reduced to O(W*2*2) as for computing some dp[i][j][k] we only need to know values at current and previous i-th and k-th state. Time complexity will remain the same.

My Personal Notes arrow_drop_up
Related Articles