You’re packing a bag for a trip. Every item has a weight and a value; the bag has a capacity; you must choose a subset that maximizes total value without exceeding the limit.
Each item is either taken whole or skipped — no splitting, hence “0/1.” With a few items this is easy to eyeball; with dozens it becomes combinatorially explosive. Dynamic programming tames it by filling a table one decision at a time.
How It Works
The DP defines dp[i][w] = the best value achievable using only the first i items with a capacity of w:
- Initialize: every cell in row 0 (no items) and column 0 (no capacity) is 0.
- Skip: without the current item, the value is
dp[i-1][w]. - Take: if the item fits, the value with it is
dp[i-1][w - weight] + value. - Choose: store the maximum of the two — that’s the recurrence:
dp[i][w] = max(dp[i-1][w], dp[i-1][w - weight[i]] + value[i])
Key Insight
Every cell depends only on the cell above (skip) and the cell above-and-left (take). Because any subproblem’s optimal solution builds from optimal solutions of smaller subproblems — optimal substructure — filling the table row-by-row yields the global optimum.
The answer sits in the bottom-right cell dp[n][W]. Walking backward through the table recovers exactly which items were chosen.
Worked Example
The visualizer packs these items into a bag of capacity 7:
| Item | Weight | Value |
|---|---|---|
| Laptop | 3 | 4 |
| Camera | 2 | 3 |
| Watch | 1 | 2 |
| Bottle | 3 | 3 |
| Book | 2 | 2 |
Filling the table row by row, the bottom-right cell reaches dp[5][7] = 9. The optimal subset is Laptop (3w, 4v) + Camera (2w, 3v) + Watch (1w, 2v) = total value 4 + 3 + 2 = 9, total weight 3 + 2 + 1 = 6 ≤ 7. Watch the visualizer’s backtrack step highlight this exact path from the bottom-right cell back to the top-left, confirming each chosen item.
Edge Cases & Pitfalls
- Item heavier than capacity — the “take” option is impossible: the cell must use “skip” only (
dp[i-1][w]). - Zero-capacity column — nothing fits: every cell is 0.
- Huge capacities —
O(nW)is pseudo-polynomial: fine for moderateW, but exponential in the bit length ofW. This is why knapsack is NP-hard in general. - Ties — multiple subsets can tie for max value; backtracking returns one of them.
- Empty item set — row 0 is all zeros: the answer is 0.
Comparison: 0/1 vs Fractional Knapsack
| Aspect | 0/1 Knapsack | Fractional Knapsack |
|---|---|---|
| Items divisible | No | Yes |
| Best approach | DP | Greedy (ratio) |
| Complexity | O(nW) | O(n log n) |
| Optimal | Yes | Yes (for its problem) |
Applications
- Resource allocation — project selection under a fixed budget
- Cargo loading — maximizing shipment value under weight limits
- Portfolio optimization — selecting investments under a capital cap
Practice Trajectory
- Hand-fill the dp table for the visualizer’s items and confirm the bottom-right value.
- Explain why every cell depends only on the cell above and above-left.
- Backtrack from the optimum by hand to recover the chosen items.
- Construct an instance where a greedy ratio approach fails for 0/1.
- Implement the
O(W)space optimization that drops the item dimension (length only).