洛谷 P1858 多人背包

求01背包前k优解的价值和
输入输出格式 Input/output
输入格式:
第一行三个数K、V、N(k<=50,v<=5000,n<=200)
接下来每行两个数,表示体积和价值
输出格式:
前k优解的价值和

解题思路:

这个题刚开始没做出来只能说是因为我没有认真地去看那个叫背包九讲的东西(这里附网址 http://wenku.baidu.com/view/519124da5022aaea998f0f22.html)

背包九讲中第九讲明确给出求次小值及第k小值的办法,做两个队列,b1,b2,用于储存选这个物品和不选这个物品的最大价值,然后取最大值进行合并(类似归并排序)

 1 program ManyBag;
 2 var ans,i,j,l,q1,q2,t,k,n,v,sv,w:longint;
 3     f:Array[0..50,0..5000] of longint;//f[i,j]表示第i大的背包,在体积为j时的体积
 4     b1,b2:array[1..50] of longint;
 5 begin
 6     read(k,sv,n);
 7     for i:=0 to sv do
 8     for j:=0 to k do f[j,i]:=-1000;//对数组赋一个极小值
 9     f[1,0]:=0;//第1大的数值在体积为0时价值为0
10     for i:=1 to n do
11     begin
12         read(v,w);
13         for j:=sv downto v do if f[1,j-v]>=0 then
14         begin
15             fillchar(b1,sizeof(b1),0);
16             fillchar(b2,sizeof(b2),0);
17             q1:=1; q2:=1;
18             for l:=1 to k do
19             begin
20                 b1[l]:=f[l,j];//不选的队列
21                 b2[l]:=f[l,j-v]+w;//选的队列
22                 if b1[q1]>b2[q2] then
23                 begin
24                     f[l,j]:=b1[q1];
25                     inc(q1);//用下一个数比较
26                 end
27                 else
28                 begin
29                     f[l,j]:=b2[q2];
30                     inc(q2);
31                 end;
32             end;
33         end;
34     end;
35     for i:=1 to k do ans:=ans+f[i,sv];
36     writeln(ans);
37 end.

 

posted @ 2015-08-13 20:34  Alisahhh  阅读(329)  评论(0编辑  收藏  举报