procedure2012
It's not worth it to know you're not worth it!

[题目来源]:

[关键字]:背包

[题目大意]:给出n个面额和每个面额的数量,问在不超过给定限制的情况下最大可达到多少。

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

[分析]:多重背包。把每件物品价值看成面额,体积也看成面额,背包容量限制为给定限制,多重背包求最大价值。方程:f[k] = f[k] or f[k-w[i]],f[k]指容量为k可不可行。由于此题直接把多重背包转换成01背包会导致空间过大,所以要用到进制优化(类似ST算法)。此处有点复杂,建议仔细研究《背包9讲》。

[代码]:

View Code
 1 program project1;
2 var
3 n, m: longint;
4 v: array[0..2000] of int64;
5 f: array[0..200000] of boolean;
6 s: array[0..300] of longint;
7
8 procedure init;
9 var
10 i, j, tot, x, y, temp: longint;
11 begin
12 read(n,m);
13 tot := 0;
14 for i := 1 to m do
15 begin
16 read(x,y);
17 temp := 0;
18 while x >= s[temp] do
19 begin
20 inc(tot);
21 v[tot] := s[temp]*y;
22 dec(x,s[temp]);
23 inc(temp);
24 end;
25 if x >= 0 then
26 begin
27 inc(tot);
28 v[tot] := y*x;
29 end;
30 end;
31 readln;
32 m := tot;
33 //writeln(m);
34 //for i := 1 to m do write(v[i],' ');
35 //writeln;
36 end;
37
38 procedure work;
39 var
40 i, j, ans: longint;
41 begin
42 fillchar(f,sizeof(f),false);
43 f[0] := true;
44 for i := 1 to m do
45 for j := n downto v[i] do
46 f[j] := f[j] or f[j-v[i]];
47 for i := n downto 0 do
48 if f[i] then
49 begin
50 writeln(i);
51 break;
52 end;
53 end;
54
55 procedure done;
56 var
57 i: longint;
58 begin
59 s[0] := 1;
60 for i := 1 to 30 do
61 s[i] := s[i-1]*2;
62 end;
63
64 begin
65 done;
66 while not seekeof() do
67 begin
68 init;
69 work;
70 end;
71 end.

 

posted on 2011-10-21 00:38  procedure2012  阅读(147)  评论(0编辑  收藏  举报