Unbounded Knapsack (Repetition of items allowed) | Efficient Approach

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 algorithmint 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 Codeint 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. |
Java
import java.io.*;import java.lang.*;import java.util.*;// class to implement optimized Unbounded Knapsack algorithmclass Main { // function to implement optimized Unbounded Knapsack // algorithm public static int unboundedKnapsackBetter(int W, int[] val, int[] wt) { // find the item with highest unit value int maxDenseIndex = 0; for (int 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; } } int[] dp = new int[W + 1]; int counter = 0; boolean breaked = false; int i = 0; // dynamic programming step for (i = 0; i <= W; i++) { for (int 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 { int start = i - wt[maxDenseIndex] + 1; int times = (int)((W - start) / wt[maxDenseIndex]); int index = (W - start) % wt[maxDenseIndex] + start; return (times * val[maxDenseIndex] + dp[index]); } } // Driver Code public static void main(String[] args) { int W = 100; int[] val = { 10, 30, 20 }; int[] wt = { 5, 10, 15 }; System.out.println( unboundedKnapsackBetter(W, val, wt)); }} |
Python3
# Python Program to implement the above approachfrom fractions import Fraction# Function to implement optimized# Unbounded Knapsack algorithmdef 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 CodeW = 100val = [10, 30, 20]wt = [5, 10, 15]print(unboundedKnapsackBetter(W, val, wt)) |
C#
// C# program to implement optimized Unbounded Knapsack// algorithmusing System;public class GFG { // function to implement optimized Unbounded Knapsack // algorithm static int unboundedKnapsackBetter(int W, int[] val, int[] wt) { // find the item with highest unit value int maxDenseIndex = 0; for (int j = 1; j < val.Length; j++) { if (val[j] * 1.0 / wt[j] > val[maxDenseIndex] * 1.0 / wt[maxDenseIndex] || (val[j] * 1.0 / wt[j] == val[maxDenseIndex] * 1.0 / wt[maxDenseIndex] && wt[j] < wt[maxDenseIndex])) { maxDenseIndex = j; } } int[] dp = new int[W + 1]; int counter = 0; bool breaked = false; int x = 0; // dynamic programming step for (; x <= W; x++) { for (int j = 0; j < wt.Length; j++) { if (wt[j] <= x) { dp[x] = Math.Max(dp[x], dp[x - wt[j]] + val[j]); } } if (x - wt[maxDenseIndex] >= 0 && dp[x] - dp[x - wt[maxDenseIndex]] == val[maxDenseIndex]) { counter++; if (counter >= wt[maxDenseIndex]) { breaked = true; break; } } else { counter = 0; } } if (!breaked) { return dp[W]; } else { int start = x - wt[maxDenseIndex] + 1; int times = (W - start) / wt[maxDenseIndex]; int index = (W - start) % wt[maxDenseIndex] + start; return (times * val[maxDenseIndex] + dp[index]); } } static public void Main() { // Code int W = 100; int[] val = { 10, 30, 20 }; int[] wt = { 5, 10, 15 }; Console.WriteLine( unboundedKnapsackBetter(W, val, wt)); }}// This code is contributed by karthik. |
Javascript
// JavaScript program to implement optimized Unbounded Knapsack algorithm// Function to implement optimized// Unbounded Knapsack algorithmfunction 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 Codelet 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)
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 zambiatek!



