Open In App

Unbounded Knapsack (Repetition of items allowed)

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Share
Report issue
Report

Given a knapsack weight W and a set of n items with certain value vali and weight wti, we need to calculate the maximum amount that could make up this quantity exactly. This is different from classical Knapsack problem, here we are allowed to use unlimited number of instances of an item.

Note: N is always positive i.e greater than zero

Examples: 

Input : W = 100
val[] = {1, 30}
wt[] = {1, 50}
Output : 100
There are many ways to fill knapsack.
1) 2 instances of 50 unit weight item.
2) 100 instances of 1 unit weight item.
3) 1 instance of 50 unit weight item and 50
instances of 1 unit weight items.
We get maximum value with option 2.

Input : W = 8
val[] = {10, 40, 50, 70}
wt[] = {1, 3, 4, 5}
Output : 110
We get maximum value with one unit of
weight 5 and one unit of weight 3.
Recommended Practice

Recursive Approach: 

A simple solution is to consider all subsets of items and calculate the total weight and value of all subsets. Consider the only subsets whose total weight is smaller than W. From all such subsets, pick the maximum value subset.
Optimal Sub-structure: To consider all subsets of items, there can be two cases for every item.

Case 1: The item is included in the optimal subset.
Case 2: The item is not included in the optimal set.
Therefore, the maximum value that can be obtained from ‘n’ items is the max of the following two values.

Maximum value obtained by n-1 items and W weight (excluding nth item).
Value of nth item plus maximum value obtained by n(because of infinite supply) items and W minus the weight of the nth item (including nth item).
If the weight of ‘nth’ item is greater than ‘W’, then the nth item cannot be included and Case 1 is the only possibility.

Below is the implementation of the above approach: 

C++




/* A Naive recursive implementation of
unbounded Knapsack problem */
#include <bits/stdc++.h>
using namespace std;
  
// Returns the maximum value that
// can be put in a knapsack of capacity W
int unboundedKnapsack(int W, int wt[], int val[], int idx)
{
  
    // Base Case
    // if we are at idx 0.
    if (idx == 0) {
        return (W / wt[0]) * val[0];
    }
    // There are two cases either take element or not take.
    // If not take then
    int notTake
        = 0 + unboundedKnapsack(W, wt, val, idx - 1);
    // if take then weight = W-wt[idx] and index will remain
    // same.
    int take = INT_MIN;
    if (wt[idx] <= W) {
        take = val[idx]
            + unboundedKnapsack(W - wt[idx], wt, val,
                                idx);
    }
    return max(take, notTake);
}
  
// Driver code
int main()
{
    int W = 100;
    int val[] = { 10, 30, 20 };
    int wt[] = { 5, 10, 15 };
    int n = sizeof(val) / sizeof(val[0]);
  
    cout << unboundedKnapsack(W, wt, val, n - 1);
    return 0;
}
// This code is contributed by Sanskar.


Java




import java.io.*;
class Knapsack {
  
    // A utility function that returns
    // maximum of two integers
    static int max(int a, int b) { return (a > b) ? a : b; }
  
    // Returns the maximum value that
    // can be put in a knapsack of
    // capacity W
    static int unboundedKnapsack(int W, int wt[], int val[],
                                int idx)
    {
        // Base Case
        // if we are at idx 0.
        if (idx == 0) {
            return (W / wt[0]) * val[0];
        }
        // There are two cases either take element or not
        // take. If not take then
        int notTake
            = 0 + unboundedKnapsack(W, wt, val, idx - 1);
        // if take then weight = W-wt[idx] and index will
        // remain same.
        int take = Integer.MIN_VALUE;
        if (wt[idx] <= W) {
            take = val[idx]
                + unboundedKnapsack(W - wt[idx], wt, val,
                                    idx);
        }
        return max(take, notTake);
    }
  
    // Driver code
    public static void main(String args[])
    {
        int W = 100;
        int val[] = { 10, 30, 20 };
        int wt[] = { 5, 10, 15 };
        int n = val.length;
        System.out.println(
            unboundedKnapsack(W, wt, val, n - 1));
    }
}
// This code is contributed by Sanskar.


Python3




# Python3 program to find maximum
# achievable value with a knapsack
# of weight W and multiple instances allowed.
  
# Returns the maximum value
# with knapsack of W capacity
# A Naive recursive implementation of unbounded Knapsack problem 
def unboundedKnapsack(W, index, val, wt):
  
    #Base case of recursion when only one element is there.
    if index==0 :return (W//wt[0])*val[0]
    #If the element with referred by index is doesn't occur even once in the required solution
    notTake=0+unboundedKnapsack(W,index-1,val,wt)
    #If the element is occur atleast once in the required solution
    take=-100000
    if wt[index]<=W:
        take=val[index]+unboundedKnapsack(W-wt[index],index,val,wt)
    return max(take,notTake)    
  
  
# Driver program
W = 100
val = [10, 30, 20]
wt = [5, 10, 15]
n = len(val)
  
print(unboundedKnapsack(W, n-1, val, wt))


C#




using System;
  
class Program
{
    // Returns the maximum value that
    // can be put in a knapsack of capacity W
    static int unboundedKnapsack(int W, int[] wt, int[] val, int idx)
    {
        // Base Case
        // if we are at idx 0.
        if (idx == 0)
        {
            return (W / wt[0]) * val[0];
        }
        // There are two cases either take element or not take.
        // If not take then
        int notTake
            = 0 + unboundedKnapsack(W, wt, val, idx - 1);
        // if take then weight = W-wt[idx] and index will remain
        // same.
        int take = Int32.MinValue;
        if (wt[idx] <= W)
        {
            take = val[idx]
                + unboundedKnapsack(W - wt[idx], wt, val,
                                    idx);
        }
        return Math.Max(take, notTake);
    }
  
    // Driver code
    public static void Main()
    {
        int W = 100;
        int[] val = { 10, 30, 20 };
        int[] wt = { 5, 10, 15 };
        int n = val.Length;
  
        Console.WriteLine(unboundedKnapsack(W, wt, val, n - 1));
    }
}


Javascript




      /* A Naive recursive implementation of
unbounded Knapsack problem */
  
      // Returns the maximum value that
      // can be put in a knapsack of capacity W
      function unboundedKnapsack(W, wt, val, idx)
      {
        
        // Base Case
        // if we are at idx 0.
        if (idx == 0) {
          return Math.floor(W / wt[0]) * val[0];
        }
          
        // There are two cases either take element or not take.
        // If not take then
        var notTake = 0 + unboundedKnapsack(W, wt, val, idx - 1);
          
        // if take then weight = W-wt[idx] and index will remain
        // same.
        var take = Number.MIN_VALUE;
        if (wt[idx] <= W) {
          take = val[idx] + unboundedKnapsack(W - wt[idx], wt, val, idx);
        }
        return Math.max(take, notTake);
      }
  
      // Driver code
      var W = 100;
      var val = [10, 30, 20];
      var wt = [5, 10, 15];
      var n = val.length;
  
      console.log(unboundedKnapsack(W, wt, val, n - 1));
        
      // This code is contributed by satwiksuman.


Output

300

Time complexity: O(W*n), where W is the capacity of the knapsack and n is the number of items.

Space complexity: O(W*n) as we are using a 2D array to store the results.

Memoization:  Like other typical Dynamic Programming(DP) problems, re-computation of same subproblems can be avoided by constructing a temporary array K[][] in bottom-up manner. Following is Dynamic Programming based implementation.

C++




/* A Naive recursive implementation of
 unbounded Knapsack problem */
#include <bits/stdc++.h>
using namespace std;
  
// Returns the maximum value that
// can be put in a knapsack of capacity W
int unboundedKnapsack(int W, int wt[], int val[], int idx,
                      vector<vector<int> >& dp)
{
  
    // Base Case
    // if we are at idx 0.
    if (idx == 0) {
        return (W / wt[0]) * val[0];
    }
    // If the value is already calculated then we will
    // previous calculated value
    if (dp[idx][W] != -1)
        return dp[idx][W];
    // There are two cases either take element or not take.
    // If not take then
  
    int notTake
        = 0 + unboundedKnapsack(W, wt, val, idx - 1, dp);
    // if take then weight = W-wt[idx] and index will remain
    // same.
    int take = INT_MIN;
    if (wt[idx] <= W) {
        take = val[idx]
               + unboundedKnapsack(W - wt[idx], wt, val,
                                   idx, dp);
    }
    return dp[idx][W] = max(take, notTake);
}
  
// Driver code
int main()
{
    int W = 100;
    int val[] = { 10, 30, 20 };
    int wt[] = { 5, 10, 15 };
    int n = sizeof(val) / sizeof(val[0]);
    vector<vector<int> > dp(n, vector<int>(W + 1, -1));
    cout << unboundedKnapsack(W, wt, val, n - 1, dp);
    return 0;
}
// This code is contributed by Sanskar.


Java




import java.io.*;
import java.util.Arrays;
  
class Knapsack {
  
    // A utility function that returns
    // maximum of two integers
    static int max(int a, int b) { return (a > b) ? a : b; }
  
    // Returns the maximum value that
    // can be put in a knapsack of
    // capacity W
    static int unboundedKnapsack(int W, int wt[], int val[],
                                 int idx, int dp[][])
    {
        // Base Case
        // if we are at idx 0.
        if (idx == 0) {
            return (W / wt[0]) * val[0];
        }
  
        // If the value is already calculated then we will
        // previous calculated value
        if (dp[idx][W] != -1)
            return dp[idx][W];
        // There are two cases either take element or not
        // take. If not take then
        int notTake
            = 0
              + unboundedKnapsack(W, wt, val, idx - 1, dp);
        // if take then weight = W-wt[idx] and index will
        // remain same.
        int take = Integer.MIN_VALUE;
        if (wt[idx] <= W) {
            take = val[idx]
                   + unboundedKnapsack(W - wt[idx], wt, val,
                                       idx, dp);
        }
        return dp[idx][W] = max(take, notTake);
    }
  
    // Driver code
    public static void main(String args[])
    {
        int W = 100;
        int val[] = { 10, 30, 20 };
        int wt[] = { 5, 10, 15 };
        int n = val.length;
        int[][] dp = new int[n][W + 1];
        for (int row[] : dp)
            Arrays.fill(row, -1);
        System.out.println(
            unboundedKnapsack(W, wt, val, n - 1, dp));
    }
}
// This code is contributed by Sanskar.


Python3




def unboundedKnapsack(W, wt, val, idx, dp):
    # Base Case
    # if we are at idx 0.
    if idx == 0:
        return (W // wt[0]) * val[0]
    # If the value is already calculated then we will
    # previous calculated value
    if dp[idx][W] != -1:
        return dp[idx][W]
    # There are two cases either take element or not take.
    # If not take then
    notTake = 0 + unboundedKnapsack(W, wt, val, idx - 1, dp)
    # if take then weight = W-wt[idx] and index will remain
    # same.
    take = float('-inf')
    if wt[idx] <= W:
        take = val[idx] + unboundedKnapsack(W - wt[idx], wt, val, idx, dp)
    dp[idx][W] = max(take, notTake)
    return dp[idx][W]
  
# Driver code
W = 100
val = [10, 30, 20]
wt = [5, 10, 15]
n = len(val)
dp = [[-1 for _ in range(W+1)] for _ in range(n)]
print(unboundedKnapsack(W, wt, val, n-1, dp))


C#




/* A Naive recursive implementation of
 unbounded Knapsack problem */
using System;
using System.Collections.Generic;
  
class Gfg
{
  // Returns the maximum value that
  // can be put in a knapsack of capacity W
  static int unboundedKnapsack(int W, int[] wt, int[] val, int idx, int [,] dp)
  {
  
    // Base Case
    // if we are at idx 0.
    if (idx == 0) {
      return (W / wt[0]) * val[0];
    }
    // If the value is already calculated then we will
    // previous calculated value
    if (dp[idx,W] != -1)
      return dp[idx,W];
    // There are two cases either take element or not take.
    // If not take then
  
    int notTake
      = 0 + unboundedKnapsack(W, wt, val, idx - 1, dp);
    // if take then weight = W-wt[idx] and index will remain
    // same.
    int take = Int32.MinValue;
    if (wt[idx] <= W) {
      take = val[idx]
        + unboundedKnapsack(W - wt[idx], wt, val,
                            idx, dp);
    }
    return dp[idx,W] = Math.Max(take, notTake);
  }
  
  // Driver code
  public static void Main(string[] args)
  {
    int W = 100;
    int[] val = { 10, 30, 20 };
    int[] wt = { 5, 10, 15 };
    int n = val.Length;
    int [,]dp=new int[n, W+1];
    for(int i=0; i<n; i++)
    {
      for(int j=0; j<W+1; j++)
        dp[i,j]=-1;
    }
    Console.Write(unboundedKnapsack(W, wt, val, n - 1, dp));
  }
}
  
// This code is contributed by ratiagrawal.


Javascript




// Returns the maximum value that
// can be put in a knapsack of capacity W
function unboundedKnapsack(W, wt, val, idx, dp) {
  // Base Case
  // if we are at idx 0.
  if (idx == 0) {
    return Math.floor(W / wt[0]) * val[0];
  }
  // If the value is already calculated then we will
  // previous calculated value
  if (dp[idx][W] != -1) return dp[idx][W];
  // There are two cases either take element or not take.
  // If not take then
 
  var notTake = 0 + unboundedKnapsack(W, wt, val, idx - 1, dp);
  // if take then weight = W-wt[idx] and index will remain
  // same.
  var take = Number.MIN_VALUE;
  if (wt[idx] <= W) {
    take = val[idx] + unboundedKnapsack(W - wt[idx], wt, val, idx, dp);
  }
  return (dp[idx][W] = Math.max(take, notTake));
}
 
// Driver code
 
var W = 100;
var val = [10, 30, 20];
var wt = [5, 10, 15];
var n = val.length;
var dp = Array(n)
  .fill()
  .map(() => Array(W + 1).fill(-1));
console.log(unboundedKnapsack(W, wt, val, n - 1, dp));
  
// This code is contributed by satwiksuman.


Output

300

Time Complexity: O(N*W)
Auxiliary Space: O(N*W) 

Dynamic Programming: Its an unbounded knapsack problem as we can use 1 or more instances of any resource. A simple 1D array, say dp[W+1] can be used such that dp[i] stores the maximum value which can achieved using all items and i capacity of knapsack. Note that we use 1D array here which is different from classical knapsack where we used 2D array. Here number of items never changes. We always have all items available.
We can recursively compute dp[] using below formula

dp[i] = 0
dp[i] = max(dp[i], dp[i-wt[j]] + val[j]
where j varies from 0
to n-1 such that:
wt[j] <= i

result = d[W]

Below is the implementation of above idea. 

C++




// C++ program to find maximum achievable value
// with a knapsack of weight W and multiple
// instances allowed.
#include<bits/stdc++.h>
using namespace std;
  
// Returns the maximum value with knapsack of
// W capacity
int unboundedKnapsack(int W, int n, 
                       int val[], int wt[])
{
    // dp[i] is going to store maximum value
    // with knapsack capacity i.
    int dp[W+1];
    memset(dp, 0, sizeof dp);
  
    // Fill dp[] using above recursive formula
    for (int i=0; i<=W; i++)
      for (int j=0; j<n; j++)
         if (wt[j] <= i)
            dp[i] = max(dp[i], dp[i-wt[j]] + val[j]);
  
    return dp[W];
}
  
// Driver program
int main()
{
    int W = 100;
    int val[] = {10, 30, 20};
    int wt[] = {5, 10, 15};
    int n = sizeof(val)/sizeof(val[0]);
  
    cout << unboundedKnapsack(W, n, val, wt);
  
    return 0;
}


Java




// Java program to find maximum achievable
// value with a knapsack of weight W and
// multiple instances allowed.
public class UboundedKnapsack 
{
      
    private static int max(int i, int j) 
    {
            return (i > j) ? i : j;
    }
      
    // Returns the maximum value with knapsack
    // of W capacity
    private static int unboundedKnapsack(int W, int n, 
                                int[] val, int[] wt) 
    {
          
        // dp[i] is going to store maximum value
        // with knapsack capacity i.
        int dp[] = new int[W + 1];
          
        // Fill dp[] using above recursive formula
        for(int i = 0; i <= W; i++){
            for(int j = 0; j < n; j++){
                if(wt[j] <= i){
                    dp[i] = max(dp[i], dp[i - wt[j]] + 
                                val[j]);
                }
            }
        }
        return dp[W];
    }
  
    // Driver program
    public static void main(String[] args) 
    {
        int W = 100;
        int val[] = {10, 30, 20};
        int wt[] = {5, 10, 15};
        int n = val.length;
        System.out.println(unboundedKnapsack(W, n, val, wt));
    }
}
// This code is contributed by Aditya Kumar 


Python3




   
# Python3 program to find maximum
# achievable value with a knapsack
# of weight W and multiple instances allowed.
  
# Returns the maximum value 
# with knapsack of W capacity
def unboundedKnapsack(W, n, val, wt):
  
    # dp[i] is going to store maximum 
    # value with knapsack capacity i.
    dp = [0 for i in range(W + 1)]
  
    ans = 0
  
    # Fill dp[] using above recursive formula
    for i in range(W + 1):
        for j in range(n):
            if (wt[j] <= i):
                dp[i] = max(dp[i], dp[i - wt[j]] + val[j])
  
    return dp[W]
  
# Driver program
W = 100
val = [10, 30, 20]
wt = [5, 10, 15]
n = len(val)
  
print(unboundedKnapsack(W, n, val, wt))
  
# This code is contributed by Anant Agarwal.


C#




// C# program to find maximum achievable
// value with a knapsack of weight W and
// multiple instances allowed.
using System;
  
class UboundedKnapsack {
      
    private static int max(int i, int j)
    {
            return (i > j) ? i : j;
    }
      
    // Returns the maximum value 
    // with knapsack of W capacity
    private static int unboundedKnapsack(int W, int n, 
                                  int []val, int []wt) 
    {
          
        // dp[i] is going to store maximum value
        // with knapsack capacity i.
        int []dp = new int[W + 1];
          
        // Fill dp[] using above recursive formula
        for(int i = 0; i <= W; i++){
            for(int j = 0; j < n; j++){
                if(wt[j] <= i){
                    dp[i] = Math.Max(dp[i], dp[i - 
                                        wt[j]] + val[j]);
                }
            }
        }
        return dp[W];
    }
  
    // Driver program
    public static void Main() 
    {
        int W = 100;
        int []val = {10, 30, 20};
        int []wt = {5, 10, 15};
        int n = val.Length;
        Console.WriteLine(unboundedKnapsack(W, n, val, wt));
    }
}
  
// This code is contributed by vt_m.


Javascript




<script>
    // Javascript program to find maximum achievable
    // value with a knapsack of weight W and
    // multiple instances allowed.
      
    function max(i, j)
    {
            return (i > j) ? i : j;
    }
       
    // Returns the maximum value
    // with knapsack of W capacity
    function unboundedKnapsack(W, n, val, wt)
    {
           
        // dp[i] is going to store maximum value
        // with knapsack capacity i.
        let dp = new Array(W + 1);
        dp.fill(0);
           
        // Fill dp[] using above recursive formula
        for(let i = 0; i <= W; i++){
            for(let j = 0; j < n; j++){
                if(wt[j] <= i){
                    dp[i] = Math.max(dp[i], dp[i - wt[j]] + val[j]);
                }
            }
        }
        return dp[W];
    }
      
    let W = 100;
    let val = [10, 30, 20];
    let wt = [5, 10, 15];
    let n = val.length;
    document.write(unboundedKnapsack(W, n, val, wt));
      
</script>


PHP




<?php
// PHP program to find maximum 
// achievable value with a 
// knapsack of weight W and 
// multiple instances allowed.
  
// Returns the maximum value 
// with knapsack of W capacity
function unboundedKnapsack($W, $n
                           $val, $wt)
{
    // dp[i] is going to store 
    // maximum value with 
    // knapsack capacity i.
    for($i = 0; $i <= $W; $i++)
        $dp[$i] = 0;
  
    $ans = 0;
      
    // Fill dp[] using above
    // recursive formula
    for ($i = 0; $i <= $W; $i++)
    for ($j = 0; $j < $n; $j++)
        if ($wt[$j] <= $i)
            $dp[$i] = max($dp[$i], 
                          $dp[$i - $wt[$j]] + 
                                   $val[$j]);
  
    return $dp[$W];
}
  
// Driver Code
$W = 100;
$val = array(10, 30, 20);
$wt = array(5, 10, 15);
$n = count($val); //sizeof($val)/sizeof($val[0]);
  
echo unboundedKnapsack($W, $n
                       $val, $wt);
  
// This code is contributed
// by shiv_bhakt
?>


Output

300

Time Complexity: O(W*N) where W is the total weight(capacity) and N is the total number of items.
Auxiliary Space: O(W) where W is the total weight.

This article is compiled using inputs from Shubham Gupta, Shubham Joshi and Ashish kumar.
 



Last Updated : 11 Sep, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads