背包问题

背包问题是动态规划的经典问题,它主要解决的是一类有一定约束情况下的最优解问题。
典型的就是你有一个容量为W的背包,有一堆商品,每个商品都有对应的重量和价值(w,v),求问你怎么装价值最大。
听起来像个贪心算法的问题,会让你想算出性价比最高的商品往里填,填不下了用性价比第二的填。
然而现实情况是,背包问题的商品是按件为最小划分单位的。比如你背包容量10kg,商品A 7kg 10元,商品B 5kg 6元,装了A就没法装B了,而装B可以装两个。
所以一般用DP动态规划来解。

01背包

每个商品只有一个,你可以选择装或者不装。
对于1维01背包,递推公式为 $ f(i,w) = max( f(i-1,w) , f(i,w-w(i))+v(i) ) $,
初始状态需要确定 f(1,w)们。(f(1,1),f(1,2),f(1,3),....,f(1,w))
其中,f(i,w)表示,只从前i个商品集里选(不一定选中哪些),在背包容量为w时的最高价值。w(i)表示商品i的重量,v(i)表示商品i的价值。
为什么递推公式这样呢?
因为在我们已经有了f(i-1,各个w)后,f(i-1,w)已经是这个子问题的最优解了,这时,我们将商品集扩大一个商品i,无非有两种情况,选i和不选i。那么我们就只需要选取这两种情况中最大值,就是“前i个商品备选,容量w”的最优解f(i,w)了。
详细可看:https://www.jianshu.com/p/f38f4af13177

完全背包

每个商品有无穷多个,你可以选0~能装下的任意件。
对于1维完全背包,递推公式为$ f(i,w) = max( f(i-1,w-w(i)k)+v(i)k ), k \geq 0 and w(i)*k \leq w $,
初始状态需要确定 f(1,w)们。

多重背包

每个商品有有限个,只能装对应的数量。
介于01背包和完全背包之间。可以转化为两者。
转化为01背包,将不同数量的商品看作不同商品。比如有3个商品1,可以将他们看作商品1a,1b和1c。
更好的办法是在完全背包的基础上对约束条件稍作修改:$ f(i,w) = max( f(i-1,w-w(i)k)+v(i)k ), k \geq 0 and k \leq n(i) and w(i)*k \leq w $
其中n(i)表示商品i最多有几件。

多维背包

其实就是限制条件从一维的重量,变成了多维的重量、体积等等。
以简单的二维01背包问题为例,递推公式只是发生了些微的变化:$ f(i,w,m) = max( f(i-1,w,m) , f(i,w-w(i),m-m(i))+v(i) ) $

posted @ 2019-09-11 19:40  大胖子球花  阅读(206)  评论(0)    收藏  举报