1.完全背包
完全背包和01背包问题唯一不同的地方就是,每种物品有无限件。
而完全背包的物品是可以添加多次的,所以要从小到大去遍历,即:
// 先遍历物品,再遍历背包
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]);
}
}
2.518零钱兑换二
1.dp[j]:代表容量为j的有多少种兑换方式
2.递推公式:dp[j] += dp[j-coins[i]];考虑所有情况下的累加。
3.初始化:默认情况下的容量为0的时候有一种兑换方式。
4.遍历顺序:个数可以无限使用,所以是完全背包问题,因为本题属于是组合问题(不需要考虑顺序),所以需要遍历的顺序是先遍历物品,再遍历容量。
class Solution {
public:
int change(int amount, vector<int>& coins) {
vector<int>dp(amount+1,0);//dp[i]容量为i的类型的数
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];
}
};
3.377组合总和四
1.dp[j]:代表容量为j的有多少种排列方式
2.递推公式:dp[j] += dp[j-nums[i]];考虑所有情况下的累加。
3.初始化:默认情况下的容量为0的时候有一种组合方式。
4.遍历顺序:个数可以无限使用,所以是完全背包问题,因为本题属于是排列问题(需要考虑顺序),所以需要遍历的顺序是先遍历容量,再遍历物品。
注意事项:你第二个的判断语句是为了判断是否有效的,不在本题考虑范围之内。
class Solution {
public:
int combinationSum4(vector<int>& nums, int target) {
vector<int> dp(target+1);//dp[i]:容量为i的组合的个数
dp[0] = 1;
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]];
}
}
return dp[target];
}
};
4.57.爬楼梯
1.dp[j]:代表容量为j的有多少种爬楼梯方式
2.递推公式:dp[j] += dp[j-i];考虑所有情况下的累加。
3.初始化:默认情况下的容量为0的时候有一种爬的方式。
4.遍历顺序:个数可以无限使用,所以是完全背包问题,因为本题属于是排列问题(需要考虑顺序),所以需要遍历的顺序是先遍历容量,再遍历物品。
#include<iostream>
#include<vector>
using namespace std;
int main(){
int n,m;
cin>>n>>m;
vector<int> dp(n+1,0);//dp[i]:爬到i需要的步数
dp[0] = 1;
//这是一个排列问题,所以先遍历容器,再遍历类别
for(int j =1;j <= n;j++){
for(int i = 1;i <= m;i++){
if(j >= i) dp[j] += dp[j-i];
}
}
cout<<dp[n];
return 0;
}