完全背包
有N件物品和一个最多能背重量为W的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每件物品都有无限个(也就是可以放入背包多次),求解将哪些物品装入背包里物品价值总和最大。
01背包和完全背包唯一不同就是体现在遍历顺序上,完全背包的物品是可以添加多次的,所以要从小到大去遍历。
// 先遍历物品,在遍历背包
void test_CompletePack() {
vector<int> weight = {1, 3, 4};
vector<int> value = {15, 20, 30};
int bagWeight = 4;
vector<int> dp(bagWeight + 1, 0);
for(int i = 0; i < weight.size(); i++) { // 遍历物品
for(int j = weight[i]; j <= bagWeight; j++) { // 遍历背包容量
dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
}
}
cout << dp[bagWeight] << endl;
}
int main() {
test_CompletePack();
}
518.零钱兑换
给定不同面额的硬币和一个总金额。写出函数来计算可以凑成总金额的硬币组合数。假设每一种面额的硬币有无限个。
1)确定dp数组及下标含义
dp[j]:凑成总金额j的货币组合数为dp[j]。
2)确定递推公式
dp[j] += dp[j - coins[i]]。
3)dp数组初始化
dp[0] = 1。
4)确定遍历顺序
外层for循环遍历物品(钱币),内层for遍历背包(金钱总额)。(代表组合数)
class Solution {
public:
int change(int amount, vector<int>& coins) {
vector<int> dp(amount+1,0);
dp[0]=1;
for(int i=0;i<coins.size();i++) {
for(int j=coins[i];j<=amount;j++) {
dp[j] += dp[j-coins[i]];
}
}
return dp[amount];
}
};
377.组合总和
给定一个由正整数组成且不存在重复数字的数组,找出和为给定目标正整数的组合的个数。
1)确定dp数组及下标含义
dp[i]: 凑成目标正整数为i的排列个数为dp[i]。
2)确定递推公式
dp[i] += dp[i - nums[j]]。
3)dp数组初始化
dp[0] = 1。
4)确定遍历顺序
外层for遍历背包,内层for循环遍历物品。(代表排列数)