讨论 / 背包理解不错的牛们过来看下[20分]
lizhixin 2010-10-18 07:37:00
点我顶贴 收藏 删除
program n162;

var n,m,i,j:longint;

w,v,f:array[0..10001]of longint;

begin

readln(n,m);

for i:=1 to n do readln(w[i],v[i]);

for j:=1 to m do

for i:=1 to n do

if (j>=w[i]) and (f[j-w[i]]+v[i]>f[j]) then f[j]:=f[j-w[i]]+v[i];

writeln(f[m]);

end.

{40}

program n162;

var n,m,i,j:longint;

w,v,f:array[0..10001]of longint;

begin

readln(n,m);

for i:=1 to n do readln(w[i],v[i]);

for i:=1 to m do f[i]:=-maxlongint;[加了这句话后]

for i:=1 to n do

for j:=1 to m do

if (j>=w[i]) and (f[j-w[i]]+v[i]>f[j]) then f[j]:=f[j-w[i]]+v[i];

writeln(f[m]);

end.

{70 (没超时!)}

program n162;

var n,m,i,j:longint;

w,v,f:array[0..10001]of longint;

begin

readln(n,m);

for i:=1 to n do readln(w[i],v[i]);

for i:=1 to m do f[i]:=-maxlongint;

for i:=1 to n do

for j:=w[i] to m do [改成这样后]

if f[j-w[i]]+v[i]>f[j] then f[j]:=f[j-w[i]]+v[i];

writeln(f[m]);

end.

{ACCEPTED}

不用说了这是道完全背包

但是我对初始值为什么赋-MAXLONGINT不理解;

还有为什么我莫名其妙改了第三次那个就AC了呢;

大牛给解释下...

#1 wish@2008-10-14 05:42:00
回复 删除
第一个问题,怎么说呢,that’s it,just it

这样处理的确就是放满的情况

我就以01背包为例解释下

如果你初始0的话,最后结果的 f[m] 可能是从某个初始0的节点转移过来(这样就不满了)。

如三个物品:

大小/价值

3/2

2/100

4/2

背包容量:7

如果不要求放满(用0初始化),则我们来看关键的几个f[]的转移:

f[0]: 0

f[1]: 0

f[2]: 100 f[0]+物品2

f[3]: 100 f[1]+物品2

f[4]: 100 f[2]+物品2

f[5]: 102 f[2]+物品1

f[6]: 102 f[3]+物品1

f[7]: 102 f[3]+物品3 or f[4]+物品1

但是要求放满的话,则不会出现有余量的转移:

f[0]: 0

f[1]: 无穷小

f[2]: 100 f[0] + 物品2

f[3]: 2 Comment:如果要放物品2,只能从f[1]转移,但是有余量的 f[1] 加上物品2的价值仍然为无穷小,所以只能放物品1。即为:f[0]+物品1

f[4]: 3 Comment:同上,只能放物品3,f[0]+物品3

f[5]: 102 f[2] + 物品1 or f[3]+物品2

f[6]: 102 f[2] + 物品3 or f[4]+物品2

f[7]: 4 显然放入物品2的不行,于是只能 物品1+物品3

不知道这样说你能不能理解

#2 wish@2008-10-14 05:45:00
回复 删除
第二个问题是你缺少定义 f[0] = 0

当然 j 从 w[i] 开始循环也可以减小复杂度

#3 lizhixin@2008-10-14 05:52:00
回复 删除
辛苦你了,先给你吧
#4 lizhixin@2008-10-14 05:55:00
回复 删除
但是我说了

不是因为超时而没过

况且F[0]默认是0;

我第三个程序也没加啊

#5 Zx.MYS_III@2008-10-14 06:27:00
回复 删除
第二个问题太神奇了,专程用小号来研究也没弄出个所以然来……
#6 lizhixin@2008-10-14 07:02:00
回复 删除
大牛再好好研究一下...

我搞不清楚

#7 wish@2008-10-14 21:06:00
回复 删除
数组默认不会自动清零

但是一般堆上的数据开始时是0的

所以让人误以为自动清零

#8 wish@2008-10-14 21:09:00
回复 删除
还有一种可能性

就是 fpc 版本比较低,或者是优化选项没有打开(可能需要-O2)

在编译的时候没有最优化处理

这样就没有条件判断的短路优化

于是即使当 j 不满足大于等于 w[i] 时仍然会访问 f[j-w[i]],此时 j-w[i] 是负值所以可能会出问题

不过貌似也不太像。。。

还有一种可能是rpless了。。。

#9 lizhixin@2008-10-14 21:29:00
回复 删除
o,那就这样吧,谢谢!
#10 Zx.MYS@2008-10-15 03:51:00
回复 删除
数组默认不会自动清零

在编译的时候没有最优化处理

这两个我都试过了,

给f[0]赋0,然后if (j>=w[i]) and (f[j-w[i]]+v[i]>f[j]) then f[j]:=f[j-w[i]]+v[i];

改成if (j>=w[i]) then if (f[j-w[i]]+v[i]>f[j]) then f[j]:=f[j-w[i]]+v[i];

无效,照样70

查看更多回复
提交回复