【笔记】【算法学习】【动态规划】背包问题总结(1)

(1)0/1背包

For i:=1 to n do

For j:=vtot downto v[i] do

F[j]:=max(f[j-v[i]]+w[i],f[j]);

如果题目要求恰好装满背包,则f数组除了f[0]初始化为0之外,其他的初始化为-maxlongint;

 

(2)完全背包(每个物品有无限件可用)

for i:=1 to n do

for j:=v[i] to vtot do

f[j]:=max(f[j],f[j-v[i]]+w[i]);

 

(3)多重背包(每个物品有有限件可以用)

Porocedure init;

Var

X,y,z,i:longint;

Begin

Readln(x,y,z);

I:=1;

While i<z do

Begin

Inc(tt);

V[tt]:=x*I;

W[tt]:=y*I;

Dec(z,i);

I:=i*2;

End;

Inc(tt);

V[tt]:=x*z;

W[tt]:=y*z;

End;

01背包

 

(4)混合背包

对所有多重背包拆分

For i:=1 to n do

If 当前物品是01背包……

If 当前物品是完全背包……

 

(5)多维费用背包

在方程上加一维即可

方法同上

这里不再写

物品总个数的限制

有时,“二维费用”的条件是以这样一种隐含的方式给出的:最多只能取M件物品。这事实上相当于每件物品多了一种“件数”的费用,每个物品的件数费用均为1,可以付出的最大件数费用为M。换句话说,设f[v][m]表示付出费用v、最多选m件时可得到的最大价值,则根据物品的类型(01、完全、多重)用不同的方法循环更新,最后在f[0..V][0..M]范围内寻找答案。注:只要是01背包,不管几维都要倒序循环

 

(6) 分组背包

for 所有的组k

for v=V..0

for 所有的i属于组k

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

注意这里的三层循环的顺序, “for v=V..0”这一层循环必须在“for 所有的i属于组k”之外。这样才能保证每一组内的物品最多只有一个会被添加到背包中。

 

(7)求方案总数

对于这类改变问法的问题,一般只需将状态转移方程中的max改成sum即可。例如若每件物品均是完全背包中的物品,转移方程即为

f[i][v]=sum{f[i-1][v],f[i][v-c[i]]}

初始条件f[0][0]=1。

(8)求最优方案总数

 

这里的最优方案是指物品总价值最大的方案。以01背包为例。

结合求最大总价值和方案总数两个问题的思路,最优方案的总数可以这样求:f[i][v]意义同前述,g[i][v]表示这个子问题的最优方案的总数,则在求f[i][v]的同时求g[i][v]的伪代码如下:

for i=1..N

for v=0..V

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

g[i][v]=0

if(f[i][v]==f[i-1][v])

inc(g[i][v],g[i-1][v])

if(f[i][v]==f[i-1][v-c[i]]+w[i])

inc(g[i][v],g[i-1][v-c[i]])

{考虑一下一维的如何实现}

 

我发现背包这个东西真的是好强大,和以前看的感觉完全不一样,今天先写到这里吧,明天我会继续写的。

加油!

posted @ 2010-11-09 20:58  liukee  阅读(729)  评论(1编辑  收藏  举报