01背包问题和完全背包问题,一个不理解的关键。
01背包问题
题目
有N件物品和一个容量为V的背包。第i件物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使价值总和最大。
基本思路
这是最基础的背包问题,特点是:每种物品仅有一件,可以选择放或不放。
用子问题定义状态:即f[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值。则其状态转移方程便是:
f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]}
这个方程非常重要,基本上所有跟背包相关的问题的方程都是由它衍生出来的。所以有必要将它详细解释一下:“将前i件物品放入容量为v的背包中”这个子问题,若只考虑第i件物品的策略(放或不放),那么就可以转化为一个只牵扯前i-1件物品的问题。如果不放第i件物品,那么问题就转化为“前i-1件物品放入容量为v的背包中”,价值为f[i-1][v];如果放第i件物品,那么问题就转化为“前i-1件物品放入剩下的容量为v-c[i]的背包中”,此时能获得的最大价值就是f[i-1][v-c[i]]再加上通过放入第i件物品获得的价值w[i]。
以上这段是复制的。如果百度查,很多地方都会是这样。
for i=1..N for v=V..0 f[v]=max{f[v],f[v-c[i]]+w[i]};
这里是倒着推。网上到处说
倒着推的理由是 如果顺着推,f[ v-c[i] ]可能是 F[i][ v-c[i] ]的值,倒着推就是f [i-1][ v-c[i] ]的值。顺推可能一个物品选取了多次。
我之前怎么都不理解。
例子
(物品数量)N=4 ,(背包容量) V=6
空间(质量) 价值
c[1] 1, w[1] 4
c[2] 2, w[2] 6
c[3] 3, w[3] 12
c[4] 2, w[4] 7
这是poj 3624的一部分代码:
for(i=1; i<=n; i++) { for(j=V; j>=c[i]; j--) { f[j] = max( f[j], f[ j-c[i] ] + w[i]); } }
f[....]=0;
i=1; c[1]=1; w[1]=4
f[6]=max(f[6]=0,f[5]=0 + 4)=4;
f[5]=max(f[5]=0,f[4]=0 + 4)=4;
f[4]=max(f[4]=0,f[3]=0 + 4)=4;
f[3]=max(f[3]=0,f[2]=0
+ 4)=4;
f[2]=max(f[2]=0,f[1]=0 + 4)=4;
f[1]=max(f[1]=0,f[0]=0
+ 4)=4;
j>=c[1]=1已经不满足,i++;
i=2;c[2]=2; w[2]=6
f[6]=max(f[6]=0,f[4]=4
+ 6)=10; //在这里 f[ v-c[i] ] 不可能是在这个i=2的情况里面 ,而是来自于i=1; 因为 。左边的v>大于右边的v-c[i];
f[5]=max(f[5]=4,f[3]=4
+ 6)=10;
......
f[2]=max(f[2]=4,f[0]=0 + 6)=6;
所以 max(A,B),中的B 来源于i-1的情况中计算出的结果。
先出现 f[6.5.4.3.2] 的值,
而 f[4.3.2.1.0] 的值就来自i-1里面的f[4.3.2.1.0]
如果改成顺推
for(i=1; i<=n; i++) { for(j=c[i]; j<=V; ++j) { f[j] = max(f[j], f[ j-c[i] ] + w[i]); } }
f[....]=0;
i=1; c[1]=1; w[1]=4
f[1]=max(f[1]=0,f[0]=0 + 4)=4;
f[2]=max(f[2]=0,f[1]=4 + 4)=8;
f[3]=max(f[3]=0,f[2]=8 + 4)=12;
f[4]=max(f[4]=0,f[3]=12 + 4)=16;
f[5]=max(f[5]=0,f[4]=16 + 4)=20;
f[6]=max(f[6]=0,f[5]=20 + 4)=24; (全部装了第一个物品,装了6个装满了)
j<=6已经不满足,i++;
...
// f[1.2.3.4.5.6] 按顺序计算出来,
而f[0.1.2.3.4.5]的值直接来源于 上面计算出来的值。
到这里,我恍然大悟。
所以
完全背包的问题就是这样的
与01背包问题不同的是,一件物品可以取多次。
for i=1..N for v=0..V f[v]=max{f[v],f[ v-c[i] ]+w[i]};
只需要顺着推。
这是poj1384的核心代码
for(i=0; i<n; ++i) { for(j=c[i]; j<=V; j++) { f[j] = min(f[j], f[ j-c[i] ] + w[i]); } }
字母已经改过,便于理解区别。