dp入门问题:01背包装下了我们的忧伤QWQ
作为一枚乐于作死...呸,乐于学习的蒟蒻,当然要学会装包的
那么简单的描述一下01背包问题:
小明有个bag,容量是m.小明面前有n个物品,每个物品有它的价值vi和它的体积wi,小明想知道用这个背包能装到的物品总价值最大是多少.
好,这就是一个最朴素的01背包问题,那么怎么解决呢.
稍加思索...dp嘛,从小问题解决到大问题.我们用一个数组dp[i][j]表示选第i件物品时容量为j可以得到的最大价值。
状态转移方程就出来啦:dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+[v[i]]);
其实01背包过程就是选与不选第i件物品,dp[i-1][j]实则就是不选第i件物品,dp[i-1][j-w[i]]+v[i]就是选了第i件物品,既然我们选了,那就要减掉它的wi再加上它的价值vi。然后在两者之间选最优方案就完美解决了
总的来说:01背包就是靠着第i-1的状态更新第i的状态
上代码:
再次开启脑洞:我们发现更新第i件物品的时候只需要用到第i-1的状态,之前的状态都可以抛弃,这样我们就可以抛弃i这个维度,只用一个维度保存j,这样做的的话,代码就变成了这样
注意这必须是逆序遍历,至于为什么呢?上面已经说过,01背包就是靠着第i-1的状态更新第i的状态,如果顺序遍历的话,第i状态的数据会覆盖掉第i-1状态的某一些数据,而这些被覆盖的数据保不准还有用于更新接下来的第i状态的,我们是要i-1更新i状态的,如果原i-1已经被覆盖成第i状态了,那么接下来就是用i状态更新i状态,显然是不符合定义的,而逆序遍历可以保证后面的数据先被更新成第i状态,前面的数据还是第i-1状态,那么用前面的数据(i-1状态)就可以保证不会出错
ps:这里可能有点绕,或许会不好理解,本来博主想用张动图解释解释的,奈何博主不会做动图QWQ,哪讲错了欢迎大家拍砖