01背包问题(01 backpack problem)

Problem

Given N items and a bag of weight capacity W. Each item has weight w[i] and value v[i]. What’s the most value this bag can hold?

E.g., N = 5, W = 10. w = [1 2 3 4 5], v = [5 4 3 2 1]

Output: 14.

  Explanation: Choose item 1 2 3 4 whose total weight is 10 and total value is 14.

Solution

dp[i][j] := the most value to get if taken from item [1:i] and weight <= j.
Then dp[N][W] is the answer to the problem.

dp[0][j] = 0 // given 0 items, the value you can get is always 0
dp[i][j] = dp[i-1][j]                  // if j < w[i], item i cannot be put into the bag
         = max(dp[i-1][j]              // don't take item i
               dp[i-1][j-w[i]] + v[i]) // take item i,
// Time: O(NW), Space: O(NW)
public int backpack(int N, int W, int[] w, int[] v) {
      int[][] dp = new int[N + 1][W + 1];
      for (int i = 1; i <= N; i++) {
            for (int j = 0; j <= W; j++) {
                  // Depends on if there is item of weight 0.
                  // If yes, j starts from 0. Otherwise, j starts from 1.
                  if (w[i - 1] > j)  {
                        dp[i][j] = dp[i - 1][j];
                  }
                  else {
                        dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - w[i - 1]] + v[i - 1]);
                  }
            }
      }
      return dp[N][V];
}

// Time: O(NW), Space: O(W)
// Since dp[i][j] only depends on dp[i - 1][k], where k <= j,
// we can use one dimension array dp[j]
public int backpack(int N, int W, int[] w, int[] v) {
      int[] dp = new int[W + 1];
      for (int i = 0; i < N; i++) {
            for (int j = W; j >= w[i]; j--) {
                  dp[j] = max(dp[j], dp[j - w[i]] + v[i]);
            }
      }
      return dp[W];
}