源码来自 代码随想录
分析:
- dp[i][j]的含义:从下标为[0-i]的物品里任意取,放进容量为j的背包,价值总和最大是多少
- 递推公式:dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i])
分为两种情况,如果背包放不下物品i,那么价值总和就是在前i-1的物品中取得的最大价值;如果背包能放下物品i,那么价值就是在背包空出i的重量之后,前i-1的物品所能贡献的最大值,再加上物品i所能带来的最大值 - 初始化:
如果背包容量j=0,不管怎么选物品,背包价值总和一定是0
如果i=0,也就是只有第0件物品可以选,就要比对物品0的重量和包包容量之间的关系:如果背包容量j< weight[0],则放不下物品0,dp[0][j] = 0;如果背包容量j>= weight[0]时,足够放编号0物品,dp[0][j] =value[0]。
其他情况我们可以都初始化为0
综合来看,就是先把二维数组初始化为0,判断当背包j>=物品0的重量时就都初始化为value[0] - 遍历顺序
先遍历物品,然后遍历背包重量:
// weight数组的大小 就是物品个数
for(int i = 1; i < weight.size(); i++) { // 遍历物品
for(int j = 0; j <= bagweight; j++) { // 遍历背包容量
if (j < weight[i]) dp[i][j] = dp[i - 1][j];
else dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);
}
先遍历背包,再遍历物品:
// weight数组的大小 就是物品个数
for(int j = 0; j <= bagweight; j++) { // 遍历背包容量
for(int i = 1; i < weight.size(); i++) { // 遍历物品
if (j < weight[i]) dp[i][j] = dp[i - 1][j];
else dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);
}
}
完整代码
#include <iostream>
#include <vector>
using namespace std;
void test_wei_bag_problem1() {
vector<int> weight = {1, 3, 4};
vector<int> value = {15, 20, 30};
int bagweight = 4;
// 二维数组初始化
vector<vector<int>> dp(weight.size(), vector<int>(bagweight + 1, 0));
for (int j = weight[0]; j <= bagweight; j++) {
dp[0][j] = value[0];
}
//遍历
for (int i = 1; i < weight.size(); i++) {
for (int j = 0; j <= bagweight; j++) {
if (j < weight[i])
dp[i][j] = dp[i - 1][j];
else
dp[i][j] =
max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);
}
}
cout << dp[weight.size() - 1][bagweight] << endl;
}
int main() { test_wei_bag_problem1(); }
一维dp01背包完整C++测试代码
void test_1_wei_bag_problem() {
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 = bagWeight; j >= weight[i]; j--) { // 遍历背包容量
dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
}
}
cout << dp[bagWeight] << endl;
}
int main() {
test_1_wei_bag_problem();
}