Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

The typical unbounded (allowed to choose unlimited amount of each item) knapsack

ID: 3601792 • Letter: T

Question

The typical unbounded (allowed to choose unlimited amount of each item) knapsack problem can be solved using the following algorithm:

// the following algorithm returns the maximum value with knapsack of C capacity aka unbounded knapsack (I can choose unlimited amount of each item)

// N = number of types of items, W[] = weight of each type of item, V[] = value of each type of item, C = the capacity limit of the knapsack, L[] = quantity of each type of item

public static int solve(int N, int[] W, int[] V, int[] L, int C) {
  
// results[i] is going to store maximum value with knapsack capacity i
int results[] = new int[C+1];
// initialise array to 0
Arrays.fill(results, 0);

// Fill dp[] using bottom up DP approach
for (int i=0; i<=C; i++)
for (int j=0; j<N; j++)
if (W[j] <= i)
results[i] = Math.max(results[i], results[i-W[j]]+V[j]);

return results[C];
}

Suppose the array L[] stores the quantity of each item that I can choose from. How do I tweak the unbounded knapsack algorithm (and make use the array L[]) to return the optimal knapsack with the additional constraint on the quantity of each item I can choose?

Explanation / Answer

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

Below is C++ implementation of above idea.

// 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);

    int ans = 0;

    // 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;

}

// 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);

    int ans = 0;

    // 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;

}