Knapsack DP

Concept

The 0/1 Knapsack problem asks: given items with weights and values, and a capacity W, maximize total value without exceeding W. Each item can be taken or skipped. Bottom-up tabulation builds a 2D table dp[i][w] where i is the number of items considered and w is the current capacity.

When to Use

  • Selecting items with weight/size constraints to maximize value
  • Budget allocation problems
  • Subset selection with a capacity limit
  • Any problem where you pick/skip items with a total constraint

Intuition

Build a table row by row. Row i represents 'best value using only the first i items'. For each item i and capacity w, you have two choices: skip item i (take dp[i-1][w]) or take it if it fits (take val[i-1] + dp[i-1][w-wt[i-1]]). Pick the max. The table fills from small subproblems (fewer items, less capacity) to the full problem. The answer is at dp[n][W] — all items considered, full capacity available.

Complexity

Time
O(n * W)
Space
O(n * W)

Template Code

cpp
#include<bits/stdc++.h>
using namespace std;

int main(){
    ios_base::sync_with_stdio(0), cin.tie(0);

    int n, W;
    cin >> n >> W;

    vector<int> val(n), wt(n);
    for(int i = 0; i < n; i++) cin >> wt[i] >> val[i];

    vector<vector<int>> dp(n+1, vector<int>(W+1, 0));

    for(int i = 1; i <= n; i++){
        for(int w = 0; w <= W; w++){
            dp[i][w] = dp[i-1][w];
            if(wt[i-1] <= w){
                dp[i][w] = max(dp[i][w], val[i-1] + dp[i-1][w-wt[i-1]]);
            }
        }
    }

    cout << dp[n][W] << "\n";

    return 0;
}

// Sample Input:
// 4 7
// 1 1
// 3 4
// 4 5
// 5 7
//
// Sample Output:
// 9