Evanyou Blog 彩带

01背包和完全背包

此题之前先分析两种常见的背包问题,01背包与完全背包

01背包:在M件物品中取出若干件物品放到背包中,每件物品对应的体积v1,v2,v3,....对应的价值为w1,w2,w3,,,,,每件物品之多拿一件。

解决方案

  考虑用动态规划的方法来解决,这里的:

  阶段是:在前N件物品中,选取若干件物品放入背包中;   状态是:在前N件物品中,选取若干件物品放入所剩空间为W的背包中的所能获得的最大价值;

  决策是:第N件物品放或者不放;  

 

 由此可以写出动态转移方程:

  我们用f[i,j]表示在前 i 件物品中选择若干件放在所剩空间为 j 的背包里所能获得的最大价值

  f[i,j]=max{f[i-1,j-Wi]+Pi (j>=Wi), f[i-1,j]} <1>

  这个方程非常重要,基本上所有跟背包相关的问题的方程都是由它衍生出来的。所以有必要将它详细解释一下:“将前i件物品放入容量为v的背包中”这个子问题,若只考虑第i件物品的策略(放或不放),那么就可以转化为一个只牵扯前i-1件物品的问题。如果不放第i件物品,那么问题就转化为“前i-1件物品放入容量为v的背包中”,价值为f[v];如果放第i件物品,那么问题就转化为“前i-1件物品放入剩下的容量为v-c的背包中”,此时能获得的最大价值就是f[v-c]再加上通过放入第i件物品获得的价值w。

可优化成一维数组的表达式

  for(i=1;i<=m;++i) <2>

  for(v=V;v>=0;v--)

 if(v>=c[i])

  f[v]=max{f[v],f[v-c]+w};

这里一定要注意次序,如果第二个for循环依次增大,则不能与<1>等价,因为f[v],f[v-c]的值不是类似于f[i-1][v],f[i-1][v-c],不信自己可以举例试试,比如2个物品,体积为2,4;价值为1,3;如果顺序,定会出现错误。

最优解法—O(VN)

  for i=1..N

  for j=0..V

  f[j]=max{f[j],f[j-c]+w}

  你会发现,这个伪代码与01背包的伪代码只有v的循环次序不同而已。为什么这样一改就可行呢?

  首先想想为什么01背包中要按照v=V..0的逆序来循环。这是因为要保证第i次循环中的状态f[v]是由状态f[v-c]递推而来。换句话说,这正是为了保证每件物品只选一次,保证在考虑“选入第i件物品”这件策略时,依据的是一个没有已经选入第i件物品的子结果f[v-c]。

  而现在完全背包的特点恰是每种物品可选无限件,所以在考虑“加选一件第i种物品”这种策略时,却正需要一个可能已选入第i种物品的子结果f[v-c],所以就可以并且必须采用v=0..V的顺序循环。这就是这个简单的程序为何成立的道理。

posted @ 2018-10-30 15:41  Stephen_F  阅读(388)  评论(0编辑  收藏  举报