完全背包
在 01背包 的基础上,每个物品可以选任意个。
完全背包的推导公式是这样的:
// 二维
for (int i = 1; i <= n; i ++)
for (int j = w[i]; j <= m; j ++)
f[i][j] = max(f[i-1][j], f[i][j - w[i]] + v[i]);
// 一维
// f[j]还没被用到,是上一层;f[j - w[i]] 被计算过了,是当前层
for (int i = 1; i <= n; i ++)
for (int j = w[i]; j <= m; j ++)
f[j] = max(f[j], f[j - w[i]] + v[i]);
这个公式是怎么来的?
f[i][j] = max(f[i-1][j], f[i-1][j-w[i]] + v[i], f[i-1][j-2*w[i]] + 2*v[i], ...)
f[i][j-w[i]] = max( f[i-1][j-w[i]], f[i-1][j-2*w[i]] + v[i],...)
f[i][j] = max(f[i-1][j], f[i][j-w[i]]+v[i])
518. 零钱兑换 II
求总和
class Solution {
public:
int change(int amount, vector<int>& coins) {
int n = coins.size();
vector<int> dp(amount + 1);
dp[0] = 1;
for (int i = 0; i < n; i ++)
for (int j = coins[i]; j <= amount; j ++)
dp[j] += dp[j - coins[i]];
return dp[amount];
}
};
377. 组合总和 Ⅳ
求组合数。如 1、3 和 3、1。使用先物品再背包的方式无法表示出组合,但是先背包再物品可以表示出3在前还是在后。
class Solution {
public:
int combinationSum4(vector<int>& nums, int target) {
int n = nums.size();
vector<int> dp(target + 1);
dp[0] = 1;
for (int i = 0; i <= target; i ++)
for (int j = 0; j < n; j ++)
if (i >= nums[j] && dp[i] < INT_MAX - dp[i - nums[j]])
dp[i] += dp[i - nums[j]];
return dp[target];
}
};