# 完全背包问题
在 01 背包基础上,每个物品可以取无数次
- 有 N 种物品和一个容量是 V 的背包,每种物品都有无限件可用。
- 第 i 种物品的体积是 vi,价值是 wi。
- 求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
- 输出最大价值。
dp[i]表示总体积为i的情况下的最大价值
代码模板
function maxValue(N, V, v, w) {
  let dp = new Array(V + 1).fill(0);
  for (let i = 0; i < N; i++) {
    // 循环物品
    for (let j = v[i]; j <= V; j++) {
      // 循环体积;从小到大;跟01背包问题反过来,表示v[i]可以取多次
      dp[j] = Math.max(dp[j], dp[j - v[i]] + w[i]);
    }
  }
  return dp[V];
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# 322. 零钱兑换 (opens new window)
求最少硬币数
class Solution {
    public int coinChange(int[] coins, int V) {
        int n = coins.length;
        int []f = new int[V+1];
        Arrays.fill(f, 0x3f3f3f3f);
        f[0] = 0;
        for (int i = 0; i < n; i++){
            for (int v = coins[i]; v<= V; v++){
                f[v] = Math.min(f[v], f[v-coins[i]]+1);
            }
        }
        return f[V] == 0x3f3f3f3f?-1:f[V] ;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
拓展:如何打印出最少硬币数的方案?输出一种即可
# 518. 零钱兑换 II (opens new window)
求兑换的方案数
class Solution {
    public int change(int V, int[] c) {
        int dp[] = new int[V+1];
        dp[0] = 1;
        for (int x : c){
            for (int v = x; v <=V; v++ ){
                dp[v] += dp[v-x];
            }
        }
        return dp[V];
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
