# Unbounded Knapsack (Repetition of items allowed) | Set 2

• Difficulty Level : Medium
• Last Updated : 10 Oct, 2022

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: Please try your approach on {IDE} first, before moving on to the solution.

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.

## 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))`

Output:

`300`

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

My Personal Notes arrow_drop_up
Related Articles