# Unbounded Knapsack (Repetition of items allowed) | Efficient Approach

Last Updated : 26 May, 2023

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

Recommended Practice

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 ` `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.`

## Java

 `import` `java.io.*;` `import` `java.lang.*;` `import` `java.util.*;`   `// class to implement optimized Unbounded Knapsack algorithm` `class` `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 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))`

## C#

 `// C# program to implement optimized Unbounded Knapsack` `// algorithm` `using` `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 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)

Previous
Next