[POJ3093 Margaritas on the River Walk]

[题目来源]:Greater New York 2006

[关键字]:背包

[题目大意]:求出使背包不能再放东西的方案数

//=================================================================================================

[分析]:一开始想求出背包容量为i时的方案数,但后来发现这样无法判断是否还有可以放入背包里的东西。看了题解后才明白要枚举。先将物品按体积升序排序,在从小到大枚举每一个最后剩余的不能装入背包的物品,此时i-1个物品必已装入背包,所以再对i+1件物品,sum-s[i-1](部分和)容量的背包,进行01背包求解方案数,并对[max(s[i-1],sum-s[i]+1),m]区间的方案数累加就行了(看不懂就看代码,我就是一边看一边就理解了)。注意s[1]>sum的情况,和一些小细节。

[代码]:

View Code
 1 program Project1;
2 var
3 tc, n, m, i: longint;
4 v: array[0..2000] of longint;
5 s: array[0..2000] of longint;
6 f: array[0..2000] of longint;
7
8 procedure init;
9 var
10 i, j, t: longint;
11 begin
12 read(n,m);
13 for i := 1 to n do read(v[i]);
14 for i := 1 to n-1 do
15 for j := i+1 to n do
16 if v[i] > v[j] then
17 begin
18 t := v[i];
19 v[i] := v[j];
20 v[j] := t;
21 end;
22 s[0] := 0;
23 for i := 1 to n do s[i] := s[i-1]+v[i];
24 //for i := 1 to n do write(v[i],' ');
25 //readln;
26 end;
27
28 procedure work(tc: longint);
29 var
30 i, j, k, st, ans: longint;
31 begin
32 ans := 0;
33 for i := 1 to n do
34 begin
35 if s[i-1] > m then break;
36 fillchar(f,sizeof(f),0);
37 f[s[i-1]] := 1;
38 for j := i+1 to n do
39 for k := m downto s[i-1]+v[j] do
40 f[k] := f[k]+f[k-v[j]];
41 if s[i-1] < m-v[i]+1 then st := m-v[i]+1 else st := s[i-1];
42 for j := st to m do
43 inc(ans,f[j]);
44 end;
45 if s[1] > m then ans := 0;
46 writeln(tc,' ',ans);
47 end;
48
49 begin
50 //assign(output,'d:\1.out');rewrite(output);
51 readln(tc);
52 for i := 1 to tc do
53 begin
54 init;
55 work(i);
56 end;
57 //close(output);
58 end.

你可能感兴趣的:(poj)