代码随想录算法训练营第四十三天 | 52.携带研究材料 518.零钱总和II 377.组合总和IV 70.爬楼梯
完全背包
有N件物品和一个最多能被重量为W的背包,第i间物品的重量为weights[i],价值为value[i],每件物品都有无限个,求解将哪些物品装入背包里,物品价值总和最大
遍历顺序:纯完全背包问题(即求装满背包后的最大价值)先遍历背包先遍历物品都是可以的
和零一背包求解的最大不同就是遍历顺序,完全背包先遍历物品和先遍历背包都可以,遍历背包时应从小到大遍历
52.携带研究材料
- dp[j]: 表示装满容量为j的背包,最大的价值为dp[j]
- 递推公式:dp[j] = max(dp[j-weights[i]] + value[i], dp[j])
- 初始化:dp[0] = 0;
- 遍历顺寻:先遍历物品和先遍历背包都可以,遍历背包时正序遍历(从小到大)
- 打印dp数组
#include <iostream>
#include <vector>
using namespace std;
int main() {
int N, V;
while(cin >> N >> V) {
// N 表示研究材料种类
// V 表示行李空间
vector<int> weights(N);
vector<int> value(N);
for(int i = 0; i < N; ++i) {
cin >> weights[i] >> value[i];
}
// dp[j] 表示容量为j的背包所装物品的最大价值
vector<int> dp(V + 1, 0);
// 递推公式: dp[j] = max(dp[j - weight[i]] + value[i], dp[j])
// 初始化: dp[j] = 0;
// 遍历顺序,先遍历物品后遍历背包都可以,下面先遍历物品
// 因为每个物品可以装多个,所以背包正序遍历
for(int i = 0; i < N; ++i) {
for(int j = 1; j <= V; ++j) {
if(j >= weights[i]) dp[j] = max(dp[j-weights[i]] + value[i], dp[j]);
}
}
cout << dp[V];
}
return 0;
}
518.零钱兑换II
- dp[j]: 凑成面额为j,有dp[j]种方法
- 递推公式:dp[j] += dp[j - coins[i]]
- 初始化: dp[0] = 1
- 遍历顺序:先遍历硬币后便利面额,面额从小到大遍历
- 打印dp数组
关于遍历顺序:
class Solution {
public:
int change(int amount, vector<int>& coins) {
// dp[j]: 表示凑成j的面额有多少种方法
vector<int> dp(amount + 1, 0);
// 递推公式: max(dp[j] = dp[j - coins[i]] + 1, dp[j])
// 初始化dp[0] = 1
dp[0] = 1;
// 遍历
for(int i = 0; i < coins.size(); ++i) {
for(int j = 1; j <= amount; ++j) {
if(j >= coins[i]) dp[j] += dp[j - coins[i]];
}
}
for(int val : dp) cout << val << " ";
return dp[amount];
}
};
377.组合总和IV
class Solution {
public:
int combinationSum4(vector<int>& nums, int target) {
vector<int> dp(target + 1, 0);
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];
}
};
57.爬楼梯
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n, m;
while(cin >> n >> m) {
// dp[j]: 表示到达第j个楼梯有多少种方法
vector<int> dp(n + 1, 0);
// 递推公式: dp[j] += dp[j-i]
dp[0] = 1;
for(int j = 1; j <= n; ++j) {
for(int i = 0; i <= m; ++i) {
if(j >= i) dp[j] += dp[j-i];
}
}
// for(int val : dp) cout << val << " ";
cout << dp[n];
}
return 0;
}