Skip to content
Related Articles
Open in App
Not now

Related Articles

Unbounded Knapsack (Repetition of items allowed) | Set 2

Improve Article
Save Article
  • Difficulty Level : Medium
  • Last Updated : 03 Feb, 2023
Improve Article
Save Article

Given an integer W, arrays val[] and wt[], where val[i] and wt[i] are the values and weights of the ith item, the task is to calculate the maximum value that can be obtained using weights not exceeding W. Note: Each weight can be included multiple times.

Examples:

Input: W = 4, val[] = {6, 18}, wt[] = {2, 3}
Output: 18
Explanation: The maximum value that can be obtained is 18, by selecting the 2nd item twice.

Input: W = 50, val[] = {6, 18}, wt[] = {2, 3}
Output: 294

Naive Approach: Refer to the previous post to solve the problem using traditional Unbounded Knapsack algorithm. Time Complexity: O(N * W)
Auxiliary Space: O(W)

Efficient Approach:  The above approach can be optimized based on the following observations:

  • Suppose the ith index gives us the maximum value per unit weight in the given data, which can be easily found in O(n).
  • For any weight X, greater than or equal to wt[i], the maximum reachable value will be dp[X – wt[i]] + val[i].
  • We can calculate the values of dp[] from 0 to wt[i] using the traditional algorithm and we can also calculate the number of instances of ith item we can fit in W weight.
  • So the required answer will be val[i] * (W/wt[i]) + dp[W%wt[i]].
     

Below is the implementation of  new algorithm.

C++




// C++ program to implement optimized Unbounded Knapsack algorithm
#include<bits/stdc++.h>
using namespace std;
 
// Function to implement optimized
// Unbounded Knapsack algorithm
int unboundedKnapsackBetter(int W, vector<int> val, vector<int> wt) {
 
  // Stores most dense item
  int maxDenseIndex = 0;
 
  // Find the item with highest unit value
  // (if two items have same unit value then choose the lighter item)
  for (int i = 1; i < val.size(); i++) {
    if (val[i] / wt[i] > val[maxDenseIndex] / wt[maxDenseIndex]
        || (val[i] / wt[i] == val[maxDenseIndex] / wt[maxDenseIndex]
            && wt[i] < wt[maxDenseIndex])) {
      maxDenseIndex = i;
    }
  }
 
  int dp[W+1] = {0};
 
  int counter = 0;
  bool breaked = false;
  int i=0;
  for (i = 0; i <= W; i++) {
    for (int j = 0; j < wt.size(); j++) {
      if (wt[j] <= i) {
        dp[i] = max(dp[i], dp[i - wt[j]] + val[j]);
      }
    }
    if (i - wt[maxDenseIndex] >= 0 && dp[i] - dp[i - wt[maxDenseIndex]] == val[maxDenseIndex]) {
      counter += 1;
      if (counter >= wt[maxDenseIndex]) {
        breaked = true;
        break;
      }
    }
    else {
      counter = 0;
    }
  }
 
  if (!breaked) {
    return dp[W];
  } else {
    int start = i - wt[maxDenseIndex] + 1;
    int times = (floor)((W - start) / wt[maxDenseIndex]);
    int index = (W - start) % wt[maxDenseIndex] + start;
    return (times * val[maxDenseIndex] + dp[index]);
  }
}
 
// Driver Code
int main(){
  int W = 100;
  vector<int> val = {10, 30, 20};
  vector<int> wt = {5, 10, 15};
  cout<<unboundedKnapsackBetter(W, val, wt);
}
 
// This code is contributed by ratiagrawal.

Python3




# Python Program to implement the above approach
 
from fractions import Fraction
 
# Function to implement optimized
# Unbounded Knapsack algorithm
def unboundedKnapsackBetter(W, val, wt):
 
    # Stores most dense item
    maxDenseIndex = 0
 
    # Find the item with highest unit value
    # (if two items have same unit value then choose the lighter item)
    for i in range(1, len(val)):
         
      if Fraction(val[i], wt[i]) \
            > Fraction(val[maxDenseIndex], wt[maxDenseIndex]) \
             or (Fraction(val[i], wt[i]) == Fraction(val[maxDenseIndex], wt[maxDenseIndex]) \
             and wt[i] < wt[maxDenseIndex] ):
                  
        maxDenseIndex = i
 
    dp = [0 for i in range(W + 1)]
 
    counter = 0
    breaked = False
    for i in range(W + 1):
        for j in range(len(wt)):
             
            if (wt[j] <= i):
                dp[i] = max(dp[i], dp[i - wt[j]] + val[j])
                 
        if i - wt[maxDenseIndex] >= 0 \
            and dp[i] - dp[i-wt[maxDenseIndex]] == val[maxDenseIndex]:
                 
            counter += 1
             
            if counter>= wt[maxDenseIndex]:
                 
                breaked = True
                # print(i)
                break
        else:
            counter = 0
 
    if not breaked:
        return dp[W]
    else:
        start = i - wt[maxDenseIndex] + 1
        times = (W - start) // wt[maxDenseIndex]
        index = (W - start) % wt[maxDenseIndex] + start
        return (times * val[maxDenseIndex] + dp[index])
         
         
# Driver Code
W = 100
val = [10, 30, 20]
wt = [5, 10, 15]
  
print(unboundedKnapsackBetter(W, val, wt))

Javascript




// JavaScript program to implement optimized Unbounded Knapsack algorithm
 
// Function to implement optimized
// Unbounded Knapsack algorithm
function unboundedKnapsackBetter(W, val, wt) {
 
    // Stores most dense item
    let maxDenseIndex = 0
 
    // Find the item with highest unit value
    // (if two items have same unit value then choose the lighter item)
    for (let i = 1; i < val.length; i++) {
        if (val[i] / wt[i] > val[maxDenseIndex] / wt[maxDenseIndex]
            || (val[i] / wt[i] === val[maxDenseIndex] / wt[maxDenseIndex]
                && wt[i] < wt[maxDenseIndex])) {
            maxDenseIndex = i;
        }
    }
 
    let dp = new Array(W + 1).fill(0);
 
    let counter = 0;
    let breaked = false;
    for (var i = 0; i <= W; i++) {
        for (let j = 0; j < wt.length; j++) {
            if (wt[j] <= i) {
                dp[i] = Math.max(dp[i], dp[i - wt[j]] + val[j]);
            }
        }
        if (i - wt[maxDenseIndex] >= 0 && dp[i] - dp[i - wt[maxDenseIndex]] === val[maxDenseIndex]) {
            counter += 1;
            if (counter >= wt[maxDenseIndex]) {
                breaked = true;
                break;
            }
        } else {
            counter = 0;
        }
    }
 
    if (!breaked) {
        return dp[W];
    } else {
        let start = i - wt[maxDenseIndex] + 1;
        let times = Math.floor((W - start) / wt[maxDenseIndex]);
        let index = (W - start) % wt[maxDenseIndex] + start;
        return (times * val[maxDenseIndex] + dp[index]);
    }
}
 
// Driver Code
let W = 100;
let val = [10, 30, 20];
let wt = [5, 10, 15];
console.log(unboundedKnapsackBetter(W, val, wt));
 
// This code is contributed by lokeshpotta20.

Output:

300

Time Complexity: O( N + min(wt[i], W) * N)
Auxiliary Space: O(W)


My Personal Notes arrow_drop_up
Related Articles

Start Your Coding Journey Now!