您的位置:首页 > 其它

庆功会(动态规划)

2016-04-08 21:47 429 查看
Description为了庆贺班级在校运动会上取得第一名的成绩,班主任决定开一场庆功会,为此拔款购买奖品奖励运动员,期望拔款金额能购买最大价值的奖品,可以补充他们的精力和体力。Input第一行二个数n(n<=500),m(m<=5000),其中n代表希望购买的物品的种数,m表示班会拨的钱数。接下来n行,每行3个数,v、w、s,分别表示第I种物品的价格、价值(价格 与 价值
是不同的概念)和购买的数量(只能买0件或s件),其中v<=100,w<=1000,s<=10Output第一行:一个数,表示此次购买能获得的最大的价值(注意!不是价格)。Sample Input
5 1000

80 20 4

40 50 9

30 50 7

40 30 6

20 20 1
Sample Output
1040



解题思路1:f[i,v]表示前i种物品装入容量为v的背包里的最大价值,状态转移方程为:
f[i,v]=max{f[i-1,v-k*w[i]]+k*c[i]|0<=k<=n[i]}(1<=i<=n,m>=v>=0,0<=k<=n[i])时间复杂度:O(V*∑n[i])程序1:var
v,w,s,f:array[0..6001]of longint;
i,j,k,n,m:longint;function max(x,y:longint):longint;
begin
if x>y then
exit(x);
exit(y);
end;begin
readln(n,m);
for i:=1 to n doreadln(v[i],w[i],s[i]);
for i:=1 to n do
for j:=m downto 0
do
for
k:=0 to s[i] dobeginif j-k*v[i]<0 then
break;f[j]:=max(f[j],f[j-k*v[i]]+w[i]*k);end;
writeln(f[m]);
end.解题思路2:这种方法就是在上一篇解题报告的基础上进行优化,即把k次循环缩减为2^x次方,就是进行预处理,把完全背包转化为0/1背包。
时间复杂度:O(V*∑n[i])程序2:var
f:array[0..10000]of int64;
a,b,v,w,s:array[0..1000]of longint;
n,m,i,j,k,num,p,x,y,z:longint;function max(a,b:longint):longint;
begin
if a>b then
exit(a);
exit(b);
end;begin
readln(n,m);
p:=0;
for i:=1 to n do
beginreadln(x,y,z);
if
z>0 then begin inc(p); a[p]:=x; b[p]:=y; s[p]:=z; end;
end;
n:=p;
num:=0;
for i:=1 to n do
beginp:=1;
while
(p*a[i]<=m) dobegininc(num);w[num]:=a[i]*p;v[num]:=b[i]*p;if (p*2-1+p*2>=s[i])
thenbeginx:=s[i]-p*2+1;if (x*a[i]<=m) thenbegininc(num);w[num]:=x*a[i];v[num]:=x*b[i];end;break;end;p:=p*2;end;
end;
n:=num;
for i:=1 to n do
for j:=m downto w[i]
dof[j]:=max(f[j],f[j-w[i]]+v[i]);
writeln(f[m]);
end.版权属于: Chris
原文地址: http://blog.sina.com.cn/s/blog_83ac6af80102v9wp.html
转载时必须以链接形式注明原始出处及本声明。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: