题意:求0/1背包的前K优解总和

k<=50 v<=5000 n<=200

思路:日常刷水

归并即可,不用排序

 1 const oo=800000000;
 2 var dp:array[0..1,0..5000,1..50]of longint;
 3     w,c,a,b:array[1..200]of longint;
 4     n,m,k1,i,j,k,x,y,ans,v:longint;
 5 
 6 begin
 7  assign(input,'data.in'); reset(input);
 8  assign(output,'Tyvj1412.out'); rewrite(output);
 9  readln(k1,m,n);
10  for i:=1 to n do read(w[i],c[i]);
11  fillchar(dp[v],sizeof(dp[v]),$cf);
12  dp[0,0,1]:=0;
13  for i:=1 to n do
14  begin
15   v:=1-v; dp[v]:=dp[1-v];
16   dp[v,0,1]:=0;
17   for j:=w[i] to m do
18   begin
19    for k:=1 to k1 do a[k]:=dp[1-v,j,k];
20    for k:=1 to k1 do b[k]:=dp[1-v,j-w[i],k]+c[i];
21    x:=1; y:=1;
22    for k:=1 to k1 do
23    begin
24     if (a[x]<0)and(b[y]<0) then begin dp[v,j,k]:=-oo; continue; end;
25     if a[x]>b[y] then begin dp[v,j,k]:=a[x]; inc(x); end
26      else begin dp[v,j,k]:=b[y]; inc(y); end;
27    end;
28   end;
29  end;
30  for i:=1 to k1 do
31   if dp[v,m,i]>=0 then ans:=ans+dp[v,m,i]
32    else break;
33  writeln(ans);
34  close(input);
35  close(output);
36 end.