0/1 Knapsack
Each row only reads the row above it, so keep one row and update it in place. For each item, let c run from W down to wt, and set dp[c] = max(dp[c], val + dp[c − wt]). Because c goes down, dp[c − wt] is still the old row when it is read, so each item is counted at most once.
dp[c] is the best value for room c using each item at most once, and this holds because the loop goes c high → low: the cell it reads, dp[c − wt], is still the value from before this item.
Problem
You have a bag that can hold a total weight of at most W. There are n items. Item i has a value val[i] and a weight wt[i].
You may take each item at most once. Choose a set of items whose total weight is at most W, so that their total value is as large as possible.
Return that largest total value. The function is int knapsack(int W, vector<int>& val, vector<int>& wt).
W, the weight limit. val and wt, two lists of the same length: the value and the weight of each item.
A single number: the largest total value of a set of items whose total weight is at most W.
Item 1 (weight 4) is worth 1 on its own. Item 2 weighs 5, which is over the limit. Item 3 (weight 1) is worth 3. Items 1 and 3 together weigh 5, which is too much, so the best is item 3 alone.
Items 2 and 3 weigh 20 + 30 = 50, exactly the limit, and are worth 100 + 120 = 220. Adding item 1 would push the weight past 50.
Every item weighs more than 3, so nothing fits.
- • 1 ≤ W ≤ 10^3
- • 1 ≤ n ≤ 10^3, and val and wt have the same length
- • 1 ≤ val[i] ≤ 10^3
- • 1 ≤ wt[i] ≤ 10^3
First, think yourself
Before opening any solution, try to answer these on paper. Use hints only when stuck — each hint is counted.
- 1.
Can I take the same item twice here? What in the statement tells me?
- 2.
For the first item, I either take it or I do not. What is left for the other items in each case?
- 3.
The room left in the bag shrinks as I take items. What should I remember about each possible room size?
- 4.
If I always take the item with the best value for its weight first, will I always get the best total? Try a small example.
- 5.
How many (number of items considered, room left) pairs are there, and could I fill them in one by one?
Brute force approach
Better approach
Optimized approach
Why does this algorithm work?
Dry run
All approaches compared
| Approach | Idea | Time | Space |
|---|---|---|---|
| Brute Force | For each item, try skipping it and taking it; keep the best total | O(2^N) | O(N) |
| Better | Fill dp[i][c] once for every (item count, room) pair; each cell is O(1) | O(N · W) | O(N · W) |
| Optimal | Keep one row dp[c]; for each item, update it with c going from W down to the item's weight | O(N · W) | O(W) |
Why does this belong to this pattern?
- “each item at most once”Each item is either in or out, and it can be used only once → 0/1 knapsack. The capacity loop runs high → low.
- “total weight at most W”The room left in the bag is the state. dp[c] stores the best value for each room c.
- “largest total value”Every cell is a max of two choices: skip the item or take it.
This is the anchor of the Knapsack pattern. The only thing that makes it 0/1 is the loop direction: going high → low means an item cannot feed itself. Subset Sum is this same row with true/false instead of values, and Ones and Zeroes adds a second capacity under the same rule.
Don't make this mistake
Going up reads dp[c − wt] after it was already updated for this same item, so the item adds its value again. On W = 4, val = [1, 2, 3], wt = [4, 5, 1], item 3 (w 1, v 3) becomes dp = 0, 3, 6, 9, 12. The answer 12 uses the weight-1 item four times. The correct answer is 3.
Take W = 50 with items (w 10, v 60), (w 20, v 100) and (w 30, v 120). The ratios are 6, 5 and 4. Greedy takes the first two (weight 30, value 160), and then item 3 does not fit into the 20 left. Items 2 and 3 are worth 220. Greedy only works when you can take part of an item.
Overwriting drops the choice to skip. On W = 4, with items (w 1, v 3) and then (w 4, v 1), the answer is 3. The overwrite sets dp[4] = 1 + dp[0] = 1 when the second item is processed, which throws away the 3.
When c < wt[i], the index c − wt[i] is negative, so the read goes outside the array. With W = 4 and an item of weight 5, the loop reads dp[−1].
Want to implement this?
Write it yourself on GeeksforGeeks, then come back and compare your code with the solutions above.
Open coding workspaceHow this concept connects to System Design & C++ Systems
Top engineering interviews test whether you understand how algorithms like DP — Knapsack translate into production architectures and low-level memory mechanics.
Foundations: Object-Oriented Principles in C++23
Class invariants, pure virtual interfaces, and RAII smart pointers.
Food Delivery System (Zomato Architecture)
Real-world machine coding application of algorithms and design patterns.
Pointers vs References Deep Dive
Pointer arithmetic and memory layout under the hood.
Virtual Method Table (vtable) & Memory Layout
Polymorphism, vptr overhead, and multiple inheritance in memory.