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