0/1 Knapsack
O(n·W)Pick a subset of items with weights and values so total weight stays within W and value is maximal. One 1-D array suffices: iterate weights DOWNWARDS so each item is used at most once; iterating upwards silently turns it into the unbounded knapsack (items reusable), which is the single most common knapsack bug. The same loop shape covers subset-sum (dp of booleans) and counting variants (dp of counts).
// use it on
CSES: Book Shop ↗
Prices are weights, pages are values, x is the capacity. Straight 0/1 knapsack: if you get double the expected pages, you iterated upwards.
// the code
// weights w[i], values v[i], capacity W
long long knapsack(vector<int>& w, vector<int>& v, int W) {
vector<long long> dp(W + 1, 0); // dp[c] = best value with capacity c
for (int i = 0; i < (int)w.size(); i++)
for (int c = W; c >= w[i]; c--) // downwards: each item once
dp[c] = max(dp[c], dp[c - w[i]] + v[i]);
return dp[W];
}
// unbounded variant (unlimited copies): loop c upwards instead.// more classics
