Unbounded Knapsack - Theory


Problem Introduction

Definition

Given n items with weights wt[] and values val[], and a knapsack of capacity W, the Unbounded Knapsack Problem maximizes the total value in the knapsack by including items any number of times (each item is infinitely available).

Real-World Significance

Classic Formulation

Input:  
  wt[] = {2, 3, 5}         // Item weights  
  val[] = {50, 100, 140}   // Item values  
  W = 10                   // Knapsack capacity  
Output: 550                // Max value = 5 * val[0] (5 items of weight 2, value 50)

Key Difference from 0/1 Knapsack

Aspect 0/1 Knapsack Unbounded Knapsack
Item Usage Each item used at most once Items used unlimited times
DP Transition After taking, move to the next item After taking, stay on same item
Real-World Analogy Packing unique items in a suitcase Buying unlimited stock of products

Practical Use Cases


Solution Approaches


1. Recursion

Intuition:
For each item, decide to take it (and stay on it) or skip it (move to next).

Recursive Formula:

maxValue(i, W) = 
  if (W == 0 || i == n): 0
  else if (wt[i] > W): maxValue(i+1, W)
  else: max( 
      val[i] + maxValue(i, W - wt[i]), // Take item (stay at `i`)
      maxValue(i+1, W)                 // Skip item (move to `i+1`)
  )

Java Code:

int knapsack(int[] wt, int[] val, int i, int W) {
    if (i == wt.length || W == 0) return 0;
    if (wt[i] > W) return knapsack(wt, val, i + 1, W);
    else {
        int take = val[i] + knapsack(wt, val, i, W - wt[i]);
        int skip = knapsack(wt, val, i + 1, W);
        return Math.max(take, skip);
    }
}
// Time: O(2^W), Space: O(W)

2. Memoization (Top-Down)

Intuition:
Cache results of overlapping subproblems in a 2D array.

DP State:
dp[i][w] = max value using first i items and capacity w.

Java Code:

int memoKnapsack(int[] wt, int[] val, int i, int W, Integer[][] dp) {
    if (i == wt.length || W == 0) return 0;
    if (dp[i][W] != null) return dp[i][W];

    if (wt[i] > W)
        dp[i][W] = memoKnapsack(wt, val, i + 1, W, dp);
    else {
        int take = val[i] + memoKnapsack(wt, val, i, W - wt[i], dp);
        int skip = memoKnapsack(wt, val, i + 1, W, dp);
        dp[i][W] = Math.max(take, skip);
    }
    return dp[i][W];
}
// Initialize dp = new Integer[n][W+1]
// Time: O(n*W), Space: O(n*W) + recursion stack

Dry Run Example (wt=[2,3], val=[50,100], W=4):

i \ w 0 1 2 3 4
0 0 0 50 50 100
1 0 0 50 100 100
2 0 0 0 0 0

Result: dp[0][4] = 100


3. Tabulation (Bottom-Up)

Intuition:
Fill a 2D DP table iteratively.

Base Case:
dp[i][0] = 0 for all i

Java Code:

int tabulateKnapsack(int[] wt, int[] val, int W) {
    int n = wt.length;
    int[][] dp = new int[n + 1][W + 1];
    
    for (int i = 1; i <= n; i++) {
        for (int w = 1; w <= W; w++) {
            if (wt[i - 1] > w)
                dp[i][w] = dp[i - 1][w]; // Skip
            else
                dp[i][w] = Math.max(
                    val[i - 1] + dp[i][w - wt[i - 1]], // Take
                    dp[i - 1][w]                        // Skip
                );
        }
    }
    return dp[n][W];
}
// Time: O(n*W), Space: O(n*W)

Dry Run Example (wt=[2,3], val=[50,100], W=4):

i \ w 0 1 2 3 4
0 0 0 0 0 0
1 0 0 50 100 150
2 0 0 50 100 150

4. Space Optimization (1D DP)

Intuition:
We can reuse the same array if we loop from w = 0 to W and consider all items at each capacity.

Java Code:

int optKnapsack(int[] wt, int[] val, int W) {
    int n = wt.length;
    int[] dp = new int[W + 1];
    
    for (int w = 0; w <= W; w++) {
        for (int i = 0; i < n; i++) {
            if (wt[i] <= w)
                dp[w] = Math.max(dp[w], val[i] + dp[w - wt[i]]);
        }
    }
    return dp[W];
}
// Time: O(n*W), Space: O(W)

Dry Run (wt=[2,3], val=[50,100], W=4):


Summary Table

Approach Time Complexity Space Complexity Notes
Recursion O(2^W) O(W) Naive and exponential
Memoization O(n*W) O(n*W) Top-down with caching
Tabulation O(n*W) O(n*W) Bottom-up, efficient
Space Optimized DP O(n*W) O(W) Most optimal for large constraints

Key Insights


Real Interview Scenario

Problem:
You're an investor with unlimited shares of stocks (values = profit, weights = capital). Maximize profit given total capital W.

Solution:
Use Unbounded Knapsack with 1D DP approach.