贝茜像她的诸多姊妹一样,因为从约翰的草地吃了太多美味的草而长出了太多的赘肉.所以约翰将她置于一个及其严格的节食计划之中.她每天不能吃多过H(5≤日≤45000)公斤的干草.贝茜只能吃一整捆干草;当她开始吃一捆干草的之后就再也停不下来了.她有一个完整
的N(1≤N≤500)捆可以给她当作晚餐的干草的清单.她自然想要尽量吃到更多的干草.很自然地,每捆干草只能被吃一次(即使在列表中相同的重量可能出现2次,但是这表示的是两捆干草,其中每捆干草最多只能被吃掉一次).
给定一个列表表示每捆干草的重量Si(1≤Si≤H),求贝茜不超过节食的限制的前提下可以吃掉多少干草(注意一旦她开始吃一捆干草就会把那一捆干草全部吃完).
第1行:两个由空格隔开的整数日和N.
第2到第N+1行:第i+l行是一个单独的整数,表示第i捆干草的重量Si.
一个单独的整数表示贝茜在限制范围内最多可以吃多少公斤的干草.
有四捆草,重量分别是15,19,20和21.贝茜在56公斤的限制范围内想要吃多少就可以吃多少.
贝茜可以吃3捆干草(重量分别为15,20,21).恰好达到她的56公斤的限制.
Gold
题解:很经典的01背包,不明白为啥都能上金组了= =
方法一:最基本的二维数组方式,这里面使用了一个滚动数组,常见于仅需要存储最近几次结果的DP问题
1 /**************************************************************
2 Problem: 3407
3 User: HansBug
4 Language: Pascal
5 Result: Accepted
6 Time:1120 ms
7 Memory:1396 kb
8 ****************************************************************/
9
10 var
11 i,j,k,l,m,n:longint;
12 a:array[0..1,0..100000] of longint;
13 b:array[0..100000] of longint;
14 function max(x,y:longint):longint;
15 begin
16 if x>y then max:=x else max:=y;
17 end;
18 begin
19 readln(m,n);
20 for i:=1 to n do readln(b[i]);
21 for i:=1 to n do
22 for j:=0 to m do
23 if j<b[i] then a[i mod 2,j]:=a[(i+1) mod 2,j] else a[i mod 2,j]:=max(a[(i+1) mod 2,j],a[(i+1) mod 2,j-b[i]]+b[i]);
24 writeln(a[n mod 2,m]);
25 readln;
26 end.
方法二:直接按照《背包九讲》上面的算法,用一维数组搞定(其实核心部分的内循环只要将循环方向倒过来就可直接变成完全背包,想想为什么^_^)
1 /**************************************************************
2 Problem: 3407
3 User: HansBug
4 Language: Pascal
5 Result: Accepted
6 Time:488 ms
7 Memory:656 kb
8 ****************************************************************/
9
10 var
11 i,j,k,l,m,n:longint;
12 a:array[0..100000] of longint;
13 b:array[0..10000] of longint;
14 function max(x,y:longint):longint;
15 begin
16 if x>y then max:=x else max:=y;
17 end;
18 begin
19 readln(m,n);
20 for i:=1 to n do readln(b[i]);
21 for i:=1 to n do
22 for j:=m downto 0 do
23 if j>=b[i] then a[j]:=max(a[j],a[j-b[i]]+b[i]);
24 writeln(a[m]);
25 readln;
26 end.
综上,事实证明,同样时间复杂的的两种写法速度居然差了一倍QAQ,表示已吓尿