完全背包
题目链接 题目页面 (kamacoder.com)
相较于一维背包,完全背包的主要特征是在确定好最大背包的容量之后每个物体都可以被无限次选取,这时,主要需要改变就是双层for函数的结构 ,首先根据问题是排列问题还是组合问题,若是组合问题,外层仍然选用物品循环、内层选用背包循环;若是排列问题,外层则需要选用背包循环,内层选择物品数。此外,在内层顺序上,将变为从前往后:
for(int i=0;i<weight.size();i++){
for(int j=weight[i];j<bagSize;j++){
dp[j]=max(dp[j],dp[j-weight]+values[i]);
}
}
518. 零钱兑换 II
本题就是典型的完全背包问题,数组中的硬币面额可以无限制选取,同时要求的是求取可以满足加起来是全部金额的组合数,那么函数也就变成了:
for(int i=0;i<coins.size();i++){
for(int j=coins[i];j<=amount;j++){
dp[j]+=dp[j-coins[i]];
}
}
377. 组合总和 Ⅳ
本题同样是集合中的元素可以被无限制选取,但是根据答案中的组合种类来看,本题相同元素不同的排列顺序算作不同组合,故而变成了排列问题,排列问题需要外层循环为背包容量、内层为物品件,两层循环都是从0开始,且在循环中递归函数前需要添加判定条件:j>nums[i]:
for(int j=0;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]];
}
}
}