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.
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++
#include <bits/stdc++.h>
using namespace std;
int unboundedKnapsack( int W, int wt[], int val[], int idx)
{
if (idx == 0) {
return (W / wt[0]) * val[0];
}
int notTake
= 0 + unboundedKnapsack(W, wt, val, idx - 1);
int take = INT_MIN;
if (wt[idx] <= W) {
take = val[idx]
+ unboundedKnapsack(W - wt[idx], wt, val,
idx);
}
return max(take, notTake);
}
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;
}
|
Java
import java.io.*;
class Knapsack {
static int max( int a, int b) { return (a > b) ? a : b; }
static int unboundedKnapsack( int W, int wt[], int val[],
int idx)
{
if (idx == 0 ) {
return (W / wt[ 0 ]) * val[ 0 ];
}
int notTake
= 0 + unboundedKnapsack(W, wt, val, idx - 1 );
int take = Integer.MIN_VALUE;
if (wt[idx] <= W) {
take = val[idx]
+ unboundedKnapsack(W - wt[idx], wt, val,
idx);
}
return max(take, notTake);
}
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 ));
}
}
|
Python3
def unboundedKnapsack(W, index, val, wt):
if index = = 0 : return (W / / wt[ 0 ]) * val[ 0 ]
notTake = 0 + unboundedKnapsack(W,index - 1 ,val,wt)
take = - 100000
if wt[index]< = W:
take = val[index] + unboundedKnapsack(W - wt[index],index,val,wt)
return max (take,notTake)
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
{
static int unboundedKnapsack( int W, int [] wt, int [] val, int idx)
{
if (idx == 0)
{
return (W / wt[0]) * val[0];
}
int notTake
= 0 + unboundedKnapsack(W, wt, val, idx - 1);
int take = Int32.MinValue;
if (wt[idx] <= W)
{
take = val[idx]
+ unboundedKnapsack(W - wt[idx], wt, val,
idx);
}
return Math.Max(take, notTake);
}
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
function unboundedKnapsack(W, wt, val, idx)
{
if (idx == 0) {
return Math.floor(W / wt[0]) * val[0];
}
var notTake = 0 + unboundedKnapsack(W, wt, val, idx - 1);
var take = Number.MIN_VALUE;
if (wt[idx] <= W) {
take = val[idx] + unboundedKnapsack(W - wt[idx], wt, val, idx);
}
return Math.max(take, notTake);
}
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));
|
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++
#include <bits/stdc++.h>
using namespace std;
int unboundedKnapsack( int W, int wt[], int val[], int idx,
vector<vector< int > >& dp)
{
if (idx == 0) {
return (W / wt[0]) * val[0];
}
if (dp[idx][W] != -1)
return dp[idx][W];
int notTake
= 0 + unboundedKnapsack(W, wt, val, idx - 1, dp);
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);
}
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;
}
|
Java
import java.io.*;
import java.util.Arrays;
class Knapsack {
static int max( int a, int b) { return (a > b) ? a : b; }
static int unboundedKnapsack( int W, int wt[], int val[],
int idx, int dp[][])
{
if (idx == 0 ) {
return (W / wt[ 0 ]) * val[ 0 ];
}
if (dp[idx][W] != - 1 )
return dp[idx][W];
int notTake
= 0
+ unboundedKnapsack(W, wt, val, idx - 1 , dp);
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);
}
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));
}
}
|
Python3
def unboundedKnapsack(W, wt, val, idx, dp):
if idx = = 0 :
return (W / / wt[ 0 ]) * val[ 0 ]
if dp[idx][W] ! = - 1 :
return dp[idx][W]
notTake = 0 + unboundedKnapsack(W, wt, val, idx - 1 , dp)
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]
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#
using System;
using System.Collections.Generic;
class Gfg
{
static int unboundedKnapsack( int W, int [] wt, int [] val, int idx, int [,] dp)
{
if (idx == 0) {
return (W / wt[0]) * val[0];
}
if (dp[idx,W] != -1)
return dp[idx,W];
int notTake
= 0 + unboundedKnapsack(W, wt, val, idx - 1, dp);
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);
}
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));
}
}
|
Javascript
function unboundedKnapsack(W, wt, val, idx, dp) {
if (idx == 0) {
return Math.floor(W / wt[0]) * val[0];
}
if (dp[idx][W] != -1) return dp[idx][W];
var notTake = 0 + unboundedKnapsack(W, wt, val, idx - 1, dp);
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));
}
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));
|
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++
#include<bits/stdc++.h>
using namespace std;
int unboundedKnapsack( int W, int n,
int val[], int wt[])
{
int dp[W+1];
memset (dp, 0, sizeof dp);
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];
}
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
public class UboundedKnapsack
{
private static int max( int i, int j)
{
return (i > j) ? i : j;
}
private static int unboundedKnapsack( int W, int n,
int [] val, int [] wt)
{
int dp[] = new int [W + 1 ];
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];
}
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));
}
}
|
Python3
def unboundedKnapsack(W, n, val, wt):
dp = [ 0 for i in range (W + 1 )]
ans = 0
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]
W = 100
val = [ 10 , 30 , 20 ]
wt = [ 5 , 10 , 15 ]
n = len (val)
print (unboundedKnapsack(W, n, val, wt))
|
C#
using System;
class UboundedKnapsack {
private static int max( int i, int j)
{
return (i > j) ? i : j;
}
private static int unboundedKnapsack( int W, int n,
int []val, int []wt)
{
int []dp = new int [W + 1];
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];
}
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));
}
}
|
Javascript
<script>
function max(i, j)
{
return (i > j) ? i : j;
}
function unboundedKnapsack(W, n, val, wt)
{
let dp = new Array(W + 1);
dp.fill(0);
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
function unboundedKnapsack( $W , $n ,
$val , $wt )
{
for ( $i = 0; $i <= $W ; $i ++)
$dp [ $i ] = 0;
$ans = 0;
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 ];
}
$W = 100;
$val = array (10, 30, 20);
$wt = array (5, 10, 15);
$n = count ( $val );
echo unboundedKnapsack( $W , $n ,
$val , $wt );
?>
|
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. If you like GeeksforGeeks and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.