1、0/1背包(package.pas)
AYYZOJ p1472
1 program p1472; 2 const 3 maxm=200; maxn=30; 4 var 5 m,n,i,j: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; 9 begin 10 if x>y then max:=x else max:=y; 11 end; 12 begin 13 readln(m,n); 14 for i:=1 to n do readln(w[i],c[i]); 15 for i:=1 to n do 16 for j:=1 to m do 17 begin 18 if j>=w[i] then f[i,j]:=max(f[i-1,j-w[i]]+c[i],f[i-1,j]) 19 else f[i,j]:=f[i-1,j]; 20 end; 21 writeln(f[n,m]); 22 end.
2、采药(medic.pas)
AYYZOJ p1052
COGS p68
1 const 2 maxm=1000; maxn=100; 3 var 4 f:array[0..maxn,0..maxm] of integer; 5 w,c:array[1..maxn] of integer; 6 m,n,i,j:integer; 7 8 function max(x,y:integer):integer; 9 begin 10 if x>y then max:=x else max:=y 11 end; 12 13 begin 14 assign(input,'medic.in'); 15 reset(input); 16 assign(output,'medic.out'); 17 rewrite(output); 18 readln(m,n); 19 for i:=1 to n do readln(w[i],c[i]); 20 fillchar(f,sizeof(f),0); 21 for i:=1 to n do 22 for j:=1 to m do 23 if j>=w[i] then f[i,j]:=max(f[i-1,j-w[i]]+c[i],f[i-1,j]) 24 else f[i,j]:=f[i-1,j]; 25 writeln(f[n,m]); 26 close(input); 27 close(output); 28 end.
3、开心的金明(happy.pas)
AYYZOJ p1059
COGS p71
1 var 2 f:array[0..30000] of longint; 3 w,c:array[1..30000] of longint; 4 i,j,m,n,ans:longint; 5 begin 6 assign(input,'happy.in'); 7 reset(input); 8 assign(output,'happy.out'); 9 rewrite(output); 10 readln(m,n); 11 for i:=1 to n do readln(w[i],c[i]); 12 fillchar(f,sizeof(f),0); 13 for i:=1 to n do 14 for j:=m downto w[i] do 15 if f[j-w[i]]+c[i]*w[i]>f[j] then f[j]:=f[j-w[i]]+c[i]*w[i] 16 else f[j]:=f[j]+c[j]*w[j]; 17 writeln(f[m]); 18 close(input); 19 close(output); 20 end.
1 var 2 n,m,i,j:integer; 3 v,p:array[1..25] of longint; 4 dp:array[0..30000] of longint; 5 function max(x,y:longint):longint; 6 begin if x>y then max:=x else max:=y; end; 7 begin 8 assign(input,'happy.in'); assign(output,'happy.out'); 9 reset(input); rewrite(output); 10 readln(n,m); 11 for i:=1 to m do 12 begin 13 readln(v[i],p[i]); 14 p[i]:=p[i]*v[i]; 15 end; 16 for i:=1 to m do 17 for j:=n downto v[i] do 18 dp[j]:=max(dp[j],dp[j-v[i]]+p[i]); 19 writeln(dp[n]); 20 close(input); close(output); 21 end.
4、装箱问题(box.pas)
AYYZOJ p1021
COGS p1089
我的思路:使剩余空间最小,则可以设每件物品的价值c[i]=每件物品的体积w[i] 。转化为0/1背包问题,最后输出V-dp[v]即可
1 var 2 v,n,i,j:longint; 3 w,c:array[1..30] of longint; 4 dp:array[0..20000] of longint; 5 function max(x,y:longint):longint; 6 begin 7 if x>y then max:=x else max:=y; 8 end; 9 begin 10 assign(input,'npack.in'); 11 reset(input); 12 assign(output,'npack.out'); 13 rewrite(output); 14 readln(v); 15 readln(n); 16 for i:=1 to n do begin readln(w[i]); c[i]:=w[i]; end; 17 for i:=1 to n do 18 for j:=v downto w[i] do 19 dp[j]:=max(dp[j-w[i]]+c[i],dp[j]); 20 writeln(v-dp[v]); 21 close(input); 22 close(output); 23 end.
另一种思路:{f[j]是布尔数组,表示前i件物品正好装满容积为j的箱子,最后从后往前扫描布尔数组f,找到最大值}
1 var 2 f:array [0..20000] of boolean; 3 box:array [0..30] of integer; 4 n,v,m,i,j:longint; 5 begin 6 readln(v); 7 readln(n); 8 for i:=1 to n do read(box[i]); 9 for i:=0 to v do f[i]:=false; 10 f[0]:=true; 11 for i:=1 to n do 12 for j:=v downto box[i] do 13 if f[j-box[i]] then f[j]:=true; 14 for i:=v downto 0 do if f[i]=true then 15 begin 16 writeln(v-i); 17 halt; 18 end; 19 end.
5、竞赛真理(truth.pas/c/cpp)
AYYZOJ p1493
1 var 2 n,t,i,j:longint; 3 f:array[0..1080000] of longint; 4 w1,t1,w2,t2:array[0..30] of longint; 5 function max(a,b:longint):longint; 6 begin 7 if a>b then max:=a 8 else max:=b; 9 end; 10 begin 11 fillchar(f,sizeof(f),0); 12 readln(n,t); 13 for i:=1 to n do 14 readln(w1[i],t1[i],w2[i],t2[i]); 15 for i:=1 to n do 16 for j:=t downto 1 do 17 begin 18 if j>=t1[i] then 19 f[j]:=max(f[j-t1[i]]+w1[i],f[j]); 20 if j>=t2[i] then 21 f[j]:=max(f[j-t2[i]]+w2[i],f[j]); 22 end; 23 writeln(f[t]); 24 end.
1 var a,b:array[1..30,1..2] of longint; 2 f:array[0..1080000] of longint; 3 i,j,n,time:longint; 4 begin 5 readln(n,time); 6 for i:=1 to n do 7 read(a[i,1],b[i,1],a[i,2],b[i,2]); 8 for i:=1 to n do 9 for j:=time downto 1 do begin 10 if j>=b[i,1] then 11 if f[j]<f[j-b[i,1]]+a[i,1] then f[j]:=f[j-b[i,1]]+a[i,1]; 12 if j>=b[i,2] then 13 if f[j]<f[j-b[i,2]]+a[i,2] then f[j]:=f[j-b[i,2]]+a[i,2]; 14 end; 15 writeln(f[time]); 16 end.
【问题分析】
本题是背包问题的应用,可用动态规划来做,设 f(i,x)表示前i道题,总时间不超过x的最大得分则动态转移方程为:
f(i,x)=max(f(i-1,x-T1[i])+W1[i] ,f(i-1,x-T2[i])+W2[i],f(i-1,x))
f(n,t)即为最优解,边界条件为f(0,x)=0 ,f(i,0)=0;
由于这道题目中给出的时间T的取值较大达到1080000,如果定义成二维数组即使在Free Pascal中也无法实现,我们不妨把f(n,t)定义成两个一维数组f1(i)和f2(i),由于上次的计算结果只对当前的计算有用,所以我们把这两个数组迭代使用,直到计算出最后的结果。
1 【参考程序】1: 2 program truth; 3 const maxn=30;maxt=1080000; 4 var 5 total,n,k,i,j:longint; 6 t1,t2,w1,w2:array[1..maxn] of longint; 7 f1,f2:array[0..maxt] of longint; 8 fw:array[0..maxt] of longint; 9 function max(a,b,c:longint):longint; 10 begin 11 if a<b then a:=b; 12 if a<c then a:=c; 13 max:=a; 14 end; 15 function max2(a,b:longint):longint; 16 begin 17 if a<b then a:=b; 18 max2:=a; 19 end; 20 begin 21 assign(input,'truth.in'); 22 reset(input); 23 assign(output,'truth.out'); 24 rewrite(output); 25 readln(n,k); 26 for i:=1 to n do 27 readln(w1[i],t1[i],w2[i],t2[i]); 28 fillchar(f1,sizeof(f1),0); 29 fillchar(f2,sizeof(f2),0); 30 for i:=1 to n do 31 begin 32 for j:=1 to k do 33 if (j>=t1[i]) and (j>=t2[i]) 34 then f2[j]:=max(f1[j-t1[i]]+w1[i],f1[j-t2[i]]+w2[i],f1[j]) 35 else 36 if j>=t1[i] then f2[j]:=max2(f1[j-t1[i]]+w1[i],f1[j]) 37 else if j>=t2[i] then f2[j]:=max2(f1[j-t2[i]]+w2[i],f1[j]) 38 else f2[j]:=f1[j]; 39 for j:=0 to k do f1[j]:=f2[j]; 40 end; 41 writeln(f2[k]); 42 close(output); 43 close(input) 44 end. 45 【参考程序】2 46 var a,b:array[1..30,1..2] of longint; 47 f1:array[0..600000] of longint; 48 i,j,n,time:longint; 49 begin 50 assign(input,'truth.int');reset(input); 51 assign(output,'truth.out');rewrite(output); 52 readln(n,time); 53 for i:=1 to n do 54 read(a[i,1],b[i,1],a[i,2],b[i,2]); 55 for i:=1 to n do 56 for j:=time downto 1 do begin 57 if j>b[i,1] then 58 if f1[j]<f1[j-b[i,1]]+a[i,1] then f1[j]:=f1[j-b[i,1]]+a[i,1]; 59 if j>b[i,2] then 60 if f1[j]<f1[j-b[i,2]]+a[i,2] then f1[j]:=f1[j-b[i,2]]+a[i,2]; 61 { f1:=f2;} 62 end; 63 writeln(f1[time]); 64 65 end. 66 67 参考程序3: 68 var 69 i,j,n,t:longint; 70 v1,w1,v2,w2:array[1..30]of longint; 71 f:array[0..1080000]of longint; 72 begin 73 assign(input,'truth.in'); 74 reset(input); 75 assign(output,'truth.out'); 76 rewrite(output); 77 readln(n,t); 78 for i:=1 to n do read(v1[i],w1[i],v2[i],w2[i]); 79 for i:=1 to n do 80 for j:=t downto 0 do begin 81 if(j>=w1[i])and(f[j-w1[i]]+v1[i]>f[j])then f[j]:=f[j-w1[i]]+v1[i]; 82 if(j>=w2[i])and(f[j-w2[i]]+v2[i]>f[j])then f[j]:=f[j-w2[i]]+v2[i]; 83 end; 84 writeln(f[t]); 85 close(input); 86 close(output); 87 end.