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

• Difficulty Level : Medium
• Last Updated : 21 Jul, 2021

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
Explaination: 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.

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