Skip to content
Related Articles

Related Articles

Improve Article

Unbounded Knapsack (Repetition of items allowed) | Set 2

  • Last Updated : 21 Jul, 2021
Geek Week

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)

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.




My Personal Notes arrow_drop_up
Recommended Articles
Page :