0/1背包
1 program package; 2 const 3 maxm=200;maxn=30; 4 var 5 m,n,j,i:integer; 6 c,w: array[1..maxn] of integer; 7 f:array[0..maxn,0..maxm] of integer; 8 function max(x,y:integer):integer; //求x和y的最大值 9 begin 10 if x>y then max:=x else max:=y; 11 end; 12
13 BEGIN 14 assign(input,'package.in'); 15 assign(output,'package.out'); 16 reset(input); 17 rewrite(output); 18 readln(m,n); //背包容量m和物品数量n 19 for i:= 1 to n do 20 readln(w[i],c[i]); //每个物品的重量和价值 21 for i:=1 to n do 22 for j:=1 to m do 23 begin // f(i,x)表示前i件物品,总重量不超过x的最优价值 24 if j>=w[i] then f[i,j]:=max(f[i-1,j-w[i]]+c[i],f[i-1,j]) 25 else f[i,j]:=f[i-1,j]; 26 end; 27 writeln(f[n,m]); //f(n,m)为最优解 28 close(input); 29 close(output); 30 END.
使用二维数组存储各子问题时方便,但当maxm较大时不能定义二维数组f,怎么办,其实可以用一维数组。
1 program star_package; 2 var 3 i,j,k,n,m:longint; 4 f:array[0..100000]of longint; 5 w,c:array[0..2000]of longint; 6 begin 7 assign(input,'package.in'); 8 assign(output,'package.out'); 9 reset(input); 10 rewrite(output); 11 fillchar(f,sizeof(f),0); 12 readln(m,n); //背包容量m和物品数量n 13 for i:=1 to n do 14 readln(w[i],c[i]); //每个物品的重量和价值 15 for i:=1 to n do 16 for j:=m downto w[i] do //这里不能写成for j:=w[i] to m 17 if f[j-w[i]]+c[i]>f[j] then f[j]:=f[j-w[i]]+c[i]; // f(j)表示重量不超过j公斤的最大价值 18 writeln(f[m]); 19 close(input); 20 close(ouptut); 21 end.
为了输出方案,我们需要在每一步判断取还是不取某件物品时,需要把这个决策信息也记录下来,例如,我们可以修改f[i,j]为记录类型,分别记录数据和决策信息,f[i,j].d记录当前最大价值,f[i,j].s记录当前决策0或1,表示取还是不取该物品。当我们求出目标状态f[n,m]后,我们根据记录的信息从后往前就可以找出一种具体方案,具体实现方法见程序:
参考程序2:输出一种方案
1 program beibao;
2 const
3 maxm=200;maxn=30;
4 type ar=array[1..maxn] of integer;
5 stat=record
6 d:integer;
7 s:integer;
8 end;
9 var
10 m,n,j,i:integer;
11 c,w:ar;
12 f:array[0..maxn,0..maxm] of stat;
13 s:array[1..maxn] of integer;
14 function max(x,y:integer):integer;
15 begin
16 if x>y then begin max:=x; f[i,j].s:=1; end
17 else begin max:=y; f[i,j].s:=0; end;
18 end;
19 begin
20 assign(input,'beibao.in'); reset(input);
21 readln(m);
22 readln(n);
23 for i:= 1 to n do
24 read(w[i]);
25 for i:= 1 to n do
26 read(c[i]);
27 for i:=1 to m do f[0,i].d:=0;
28 for i:=1 to n do f[i,0].d:=0;
29 for i:=1 to n do
30 for j:=1 to m do
31 begin
32 if j>=w[i] then f[i,j].d:=max(f[i-1,j-w[i]].d+c[i],f[i-1,j].d)
33 else begin f[i,j].d:=f[i-1,j].d; f[i,j].s:=0; end;
34 end;
35 j:=m;
36 for i:=n downto 1 do
37 begin
38 s[i]:=f[i,j].s;
39 if f[i,j].s=1 then j:=j-w[i];
40 end;
41 writeln;
42 for i:=1 to n do
43 write(s[i]);
44 writeln;
45 writeln(f[n,m].d);
46 close(input);
47 end.
经典:背包九讲