今天接触了完全背包,即物品个数不做限制,只有背包容量的限制。对于完全背包这类问题,在进行遍历时可以不用考虑顺序,不过在求集合时有顺序之分。
问题1:518. 零钱兑换 II - 力扣(LeetCode)
给你一个整数数组 coins
表示不同面额的硬币,另给一个整数 amount
表示总金额。
请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0
。
假设每一种面额的硬币有无限个。
题目数据保证结果符合 32 位带符号整数。
思路:这里求的是组合数,dp[j]的含义是背包容量为j时的硬币组合数,应先对物品进行递归,再递归包,这样的话就避免了硬币顺序所造成的排列。代码如下:
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];
}
};
问题2:377. 组合总和 Ⅳ - 力扣(LeetCode)
给你一个由 不同 整数组成的数组 nums
,和一个目标整数 target
。请你从 nums
中找出并返回总和为 target
的元素组合的个数。
题目数据保证答案符合 32 位整数范围。
思路:该题求的则是排列数,先遍历书包再遍历硬币,代码如下:
class Solution {
public:
int combinationSum4(vector<int>& nums, int target) {
vector<int> dp(target+1,0);
dp[0]=1;
for(int j=1;j<=target;j++){
for(int i=0;i<nums.size();i++){
if(j >= nums[i] && dp[j] <= INT_MAX-dp[j-nums[i]]) dp[j]+=dp[j-nums[i]];
}
}
return dp[target];
}
};