02

Knapsack Variants

Chapter 2 • Advanced

120 min

Knapsack Variants

0/1 Knapsack

Problem

Given items with weights and values, maximize value without exceeding capacity.

Each item can be taken at most once.

DP Solution

python.js
def knapsack_01(weights, values, capacity):
    """
    0/1 Knapsack using DP.
    Time: O(n * W), Space: O(n * W)
    """
    n = len(weights)
    dp = [[0] * (capacity + 1) for _ in range(n + 1)]
    
    for i in range(1, n + 1):
        for w in range(capacity + 1):
            # Don't take item i
            dp[i][w] = dp[i-1][w]
            
            # Take item i (if weight allows)
            if weights[i-1] <= w:
                dp[i][w] = max(dp[i][w], 
                              dp[i-1][w - weights[i-1]] + values[i-1])
    
    return dp[n][capacity]

Space-Optimized

python.js
def knapsack_01_optimized(weights, values, capacity):
    """Space-optimized: O(W) space"""
    dp = [0] * (capacity + 1)
    
    for i in range(len(weights)):
        for w in range(capacity, weights[i] - 1, -1):
            dp[w] = max(dp[w], dp[w - weights[i]] + values[i])
    
    return dp[capacity]

Unbounded Knapsack

Items can be taken multiple times.

python.js
def knapsack_unbounded(weights, values, capacity):
    """Unbounded knapsack"""
    dp = [0] * (capacity + 1)
    
    for w in range(1, capacity + 1):
        for i in range(len(weights)):
            if weights[i] <= w:
                dp[w] = max(dp[w], dp[w - weights[i]] + values[i])
    
    return dp[capacity]

Fractional Knapsack

Items can be taken fractionally. Use greedy (sort by value/weight ratio).

Practice Problems

  1. 0/1 knapsack
  2. Unbounded knapsack
  3. Partition equal subset sum
  4. Target sum
  5. Coin change (unbounded)