题目:
有N件物品和⼀个最多能被重量为W 的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每


4. 确定遍历顺序
有两个遍历的维度:物品与背包重量,可以先遍历物品,然后背包在内层依次遍历,反之亦可
5. 举例推导dp数组
完整C++测试代码
void bag_problem()
{
vector<int> weight = {1,3,4};
vector<int> value = {15,20,30};
int bagWeight = 4;
//二维数组
vector<vector<int>> dp(weight.size() + 1,vector<int>(weight.size()b + 1,vector<int>(bagWeight + 1,0));
//初始化
for(int j = bagWeight; j >= weight[0];j--)
{
dp[0][j] = dp[0][j - weight[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];//此处避免下一行代码j - weight[j]访问数组越界
else dp[i][j] = max(dp[i - 1][j],dp[i - 1][j - weight[j]] + value[i[);
}
}
cout<< dp[weight.size() - 1][bagWeight] << endl;
}
int main()
{
bag_problem();
}
空间优化:
dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
3. ⼀维dp数组如何初始化
dp[j]表示:容量为j的背包,所背的物品价值可以最⼤为dp[j],那么dp[0]就应该是0,因为背包容量为0 所背的物品的最⼤价值就是0,其他的默认为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]);
}
}
注意:遍历顺序不可颠倒,外物品,内层背包,内层遍历时需要倒序,以保证物品i只被放入一次,因为如果正序,访问dp[j]的时候无法访问到dp[j - weight[i]]的在上一轮循环的历史值,因为j - weight 小于j,已经在本轮的前面被更新了。所以从后往前循环,每次取得状态不会和之前取得状态重合,这样每种物品就只取⼀次了。

⼀维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;
}
以上部分图文转载于代码随想录,仅作为个人学习使用,无商业用途,如侵必删!
这篇博客探讨了01背包问题的解决方案,利用动态规划思想,通过一维dp数组来优化空间。介绍了确定遍历顺序的重要性,强调外层遍历物品,内层倒序遍历背包以确保每件物品只被考虑一次。提供了完整的C++测试代码作为示例。
284

被折叠的 条评论
为什么被折叠?



