Unbounded Knapsack (Repetition of items allowed) | Set 2
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. |
300
Time Complexity: O( N + min(wt[i], W) * N)
Auxiliary Space: O(W)
Please Login to comment...