Skip to content
Related Articles

Related Articles

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

View Discussion
Improve Article
Save Article
Like Article
  • Difficulty Level : Expert
  • Last Updated : 27 Sep, 2021

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: 53
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 53.

 

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 <bits/stdc++.h>
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, 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




<script>
// javascript implementation for the above approach  
// Function to find the maximum  value
    function maximum(value,
                       weight , weight1,
                       flag , K , index)
    {
 
        // base condition
        if (index >= value.length) {
 
            return 0;
        }
 
        // K elements already reduced
        // to half of their weight
        if (flag == K) {
 
            // Dont include item
            var skip = maximum(value,
                               weight, weight1,
                               flag, K, index + 1);
 
            var 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
            var skip = maximum(
                value, weight,
                weight1, flag,
                K, index + 1);
 
            var full = 0;
            var 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
var value = [ 17, 20, 10, 15 ];
var weight = [ 4, 2, 7, 5 ];
var K = 1;
var W = 4;
document.write(
    maximum(value, weight, W,
            0, K, 0));
 
// This code is contributed by Princi Singh
</script>


Output

37

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


My Personal Notes arrow_drop_up
Recommended Articles
Page :

Start Your Coding Journey Now!