动态规划-01背包

理论

有N件物品和⼀个最多能被重量为W 的背包。第i件物品的重量是weight[i],得到的价值是
value[i] 。每件物品只能⽤⼀次,求解将哪些物品装⼊背包⾥物品价值总和最⼤。

思路

  • 确定dp数组的定义 

在⼀维dp数组中,dp[j]表⽰:容量为j的背包,所背的物品价值可以最⼤为dp[j]。

  •  ⼀维dp数组的递推公式

dp[j]可以通过dp[j - weight[j]]推导出来,dp[j - weight[i]]表⽰容量为j - weight[i]的背包所背
的最⼤价值。

dp[j - weight[i]] + value[i] 表⽰ 容量为 j - 物品i重量 的背包 加上 物品i的价值。(也就是容
量为j的背包,放⼊物品i了之后的价值即:dp[j])

此时dp[j]有两个选择,⼀个是取⾃⼰dp[j],⼀个是取dp[j - weight[i]] + value[i],指定是取
最⼤的,毕竟是求最⼤价值,所以递归公式为:

dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);

  • ⼀维dp数组如何初始化 

关于初始化,⼀定要和dp数组的定义吻合,否则到递推公式的时候就会越来越乱。

dp[j]表⽰:容量为j的背包,所背的物品价值可以最⼤为dp[j],那么dp[0]就应该是0,因为
背包容量为0所背的物品的最⼤价值就是0。

那么dp数组除了下标0的位置,初始为0,其他下标应该初始化多少呢?

dp数组在推导的时候⼀定是取价值最⼤的数,如果题⽬给的价值都是正整数那么⾮0下标都
初始化为0就可以了,如果题⽬给的价值有负数,那么⾮0下标就要初始化为负⽆穷。

这样才能让dp数组在递归公式的过程中取的最⼤的价值,⽽不是被初始值覆盖了。

那么我假设物品价值都是⼤于0的,所以dp数组初始化的时候,都初始为0就可以了。

  • ⼀维dp数组遍历顺序
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只被放⼊⼀次


版权声明:本文为weixin_35973945原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。