Dynamic Programming · Medium

203. 0/1 Knapsack Problem

Topics: Dynamic Programming

Solve it on DeVert Campus - free code runner

Problem

Given n items, each with a weight and a value, and a knapsack of capacity W, find the maximum total value obtainable by choosing a subset of items (each item taken whole or not at all) whose total weight doesn't exceed W.

Input and output

Input: Four lines: n; n space-separated weights; n space-separated values; the knapsack capacity W. Output: Print a single integer - the maximum total value obtainable within capacity W.

Example

Input:
3
10 20 30
60 100 120
50
Output:
220

Constraints

1 <= n <= 1000, 1 <= W <= 10^4

Key observation

The space-optimized 1D version MUST process capacities in DECREASING order when updating for each item - processing in increasing order would accidentally allow the SAME item to be used multiple times, turning it into unbounded knapsack by mistake.

Intuition

Choose a subset of items (each taken whole or not at all) to maximize value without exceeding a weight capacity. Brute force: Try every one of the 2^n possible subsets directly, checking weight and computing value for each - this is exponential, impractical for n up to 1000. Optimised: The DP table captures the reusable insight that the best value using the first i items at capacity w only depends on smaller sub-problems (fewer items, or less capacity) - filling the table bottom-up computes every needed sub-answer exactly once, turning exponential subset enumeration into a table of n*W cells.

Better - 2D DP Table

Define dp[i][w] = the maximum value achievable using only the first i items with capacity w. Fill this table bottom-up: dp[i][w] = dp[i-1][w] (skip item i) or, if item i's weight fits, also try value[i] + dp[i-1][w - weight[i]] (take item i), keeping the better of the two. Because each (i, w) state is computed exactly once from already-computed smaller states, this removes all the exponential recomputation of brute force. Time: O(n * W) Space: O(n * W)

Optimal - 1D Rolling DP Array

Notice that dp[i][w] only ever depends on the previous row, dp[i-1][*], so a single 1D array of size W+1 suffices if updated carefully: for each item, iterate w from W down to that item's weight (descending order is essential so each item is only considered once per capacity, not reused). This computes the exact same values as the 2D table but overwrites the array in place, cutting memory from O(n*W) down to O(W) while keeping the same O(n*W) time - a meaningful saving since W can be up to 10^4. Time: O(n * W) Space: O(W)

Approach 3

Recursively consider every item with two choices - take it or skip it - branching into all 2^n subsets, tracking accumulated weight and value, and discarding any branch whose weight exceeds W; take the maximum value over all feasible subsets explored. This checks every possible subset exhaustively, guaranteeing correctness, but the same (item index, remaining capacity) situation gets recomputed many times across different branches, causing exponential growth. Time: O(2^n) Space: O(n) recursion depth

Step by step

1. dp[i][w] = the best value achievable using the FIRST i items with capacity w. 2. For each item, either SKIP it (dp[i-1][w]) or TAKE it (dp[i-1][w-weight] + value, if it fits) - take the better of the two. 3. The final answer is dp[n][W].

Complexity

Time: O(n * W) - filling the DP table, one cell per (item count, capacity) combination. Space: O(n * W) for the full table (reducible to O(W) with a rolling 1D array, processing capacities in DECREASING order to avoid reusing an item within the same pass).

Edge cases

Test n = 1 (take the single item only if it fits), every item's weight exceeding W (answer is 0), and n = 1000, W = 10^4 (upper bounds) for the DP table's size.

Interview tip

Be ready to contrast this with UNBOUNDED knapsack (items reusable) and FRACTIONAL knapsack (items splittable) - all three sound similar but need genuinely different techniques (0/1 needs this exact DP, unbounded allows same-row reuse, fractional is solved by a simple greedy).

All DSA problems