2️⃣ 0/1 Knapsack Problem

🟡 IntermediateDP Pattern: 2D Grid

📋 Problem Statement

Given N items each with weight w[i] and value v[i], and a knapsack of capacity W. Each item can be taken at most once (0 or 1). Maximize total value without exceeding capacity.

💻 Solution: Bottom-Up DP

function knapsack01(array $weights, array $values, int $capacity): int {
    $n = count($weights);
    // dp[i][w] = max value using first i items, capacity w
    $dp = array_fill(0, $n+1, array_fill(0, $capacity+1, 0));

    for ($i = 1; $i <= $n; $i++) {
        for ($w = 0; $w <= $capacity; $w++) {
            if ($weights[$i-1] <= $w) {
                $dp[$i][$w] = max(
                    $dp[$i-1][$w],                          // Skip
                    $dp[$i-1][$w-$weights[$i-1]] + $values[$i-1] // Take
                );
            } else {
                $dp[$i][$w] = $dp[$i-1][$w]; // Can't take
            }
        }
    }
    return $dp[$n][$capacity];
}

// Space-optimized: O(W) space
function knapsack01Optimized(array $weights, array $values, int $capacity): int {
    $n = count($weights);
    $dp = array_fill(0, $capacity+1, 0);

    for ($i = 0; $i < $n; $i++) {
        // Go backwards to avoid reusing item
        for ($w = $capacity; $w >= $weights[$i]; $w--) {
            $dp[$w] = max($dp[$w], $dp[$w - $weights[$i]] + $values[$i]);
        }
    }
    return $dp[$capacity];
}

$w = [2,3,4,5]; $v = [3,4,5,6];
echo knapsack01($w, $v, 8); // 10
echo knapsack01Optimized($w, $v, 8); // 10

📝 DP Table Dry Run

Items: (w=2,v=3), (w=3,v=4), (w=4,v=5), (w=5,v=6) | Capacity: 8

i\w 0 1 2 3 4 5 6 7 8
0 0 0 0 0 0 0 0 0 0
1 (w=2) 0 0 3 3 3 3 3 3 3
2 (w=3) 0 0 3 4 4 7 7 7 7
3 (w=4) 0 0 3 4 5 7 8 9 9
4 (w=5) 0 0 3 4 5 7 8 9 10

Answer: 10 (items with w=3,v=4 + w=5,v=6 → total w=8, v=10)

📊 Complexity

Naive Recursion O(2ⁿ)
DP (2D) O(n*W) time, O(n*W) space
DP (1D optimized) O(n*W) time, O(W) space ⭐

Note: O(n*W) is pseudo-polynomial — it depends on W's numeric value, not input size.