RQNOJ123_多人背包_C++_Pascal

  题目:http://www.rqnoj.cn/problem/123

  不得不说,RQNOJ 的机子跑得好慢呀,5*10的数据范围本地跑 0.2s,服务器上愣是把我卡掉了,最后只好写了一份 Pascal 交上去

    本地跑

  

    OJ上跑

  

   咳咳,言归正传

  普通的背包是求出最优的那一钟方案,方程转移是 f[i][j]=max(f[i-1][j],f[i-1][j-v[i]]+w[i]),相当于把 2 个变量经比较后丢到 1 个变量里,也就是 k=1时的情况

  而现在我们需要求最优的前 k 组方案,那么可以把数组再增加一维,变成把 2k 个变量经比较后丢进k个数里,也就是 2 个线性表丢进 1 个线性表里,由于线性表内数据是单调下降的,则可以按照归并排序的做法做

  实现操作中还可以滚掉第一维,那么 j 就要递减枚举

  以下是 C++ 的,但是会TLE

 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<cstdio>
 6 #include<cmath>
 7 using namespace std;
 8 
 9 const int V=5001,K=51,maxint=2147483647;
10 int f[V][K],g[K];
11 int main()
12 {
13     int i,j,n,m,s,ans=0,q1,q2,k,w,v;
14     scanf("%d%d%d",&m,&s,&n);
15     for (i=0;i<=s;i++)
16         for (j=1;j<=m;j++) f[i][j]=-maxint;
17     f[0][1]=0;
18     for (i=1;i<=n;i++)
19     {
20         scanf("%d%d",&w,&v);
21         for (j=s;j>=w;j--)
22         {
23             if (f[j-w][1]<0) continue;
24             q1=q2=1;
25             for (k=1;k<=m;k++)
26                 if (f[j-w][q1]+v>f[j][q2]) g[k]=f[j-w][q1++]+v;
27                 else g[k]=f[j][q2++];
28             for (k=1;k<=m;k++) f[j][k]=g[k];
29         }
30     }
31     for (i=1;i<=m;i++) ans+=f[s][i];
32     printf("%d
",ans);
33     return 0;
34 }

  这个是 Pascal 的,可以AC

 1 program xqz;
 2 uses math;
 3 const maxv=5000; maxk=51;
 4 type arr=array[0..maxk] of longint;
 5 var
 6   c,w,i,j,m,n,k,mv,mk,l,r,b,p,e,s,t,v:longint;
 7   yes:boolean;
 8   f:array[0..maxv,0..maxk] of longint;
 9   ans,now:int64;
10 procedure work(var a:arr; b,c:arr);
11 var l,r:longint;
12 begin
13   l:=1; r:=1;
14   while (l+r-2<mk)and ((b[l]<>-1)or(c[r]<>-1))  do
15   begin
16     while (b[l]<>-1)and((c[r]=-1)or(b[l]>=c[r]+w))and(l+r-2<mk) do
17     begin
18       a[l+r-1]:=b[l]; inc(l);
19     end;
20     while (c[r]<>-1)and((b[l]=-1)or(b[l]<=c[r]+w))and(l+r-2<mk) do
21     begin
22       a[l+r-1]:=c[r]+w; inc(r);
23     end;
24   end;
25 end;
26 
27 begin
28   readln(mk,mv,n); fillchar(f,sizeof(f),$ff);
29   f[0,1]:=0;
30   for i:=1 to n do
31   begin
32     readln(c,w); now:=now+c;
33     for j:=min(now,mv) downto c do
34       work(f[j],f[j],f[j-c])
35   end;
36   for k:=1 to mk do
37     inc(ans,f[mv,k]);
38   writeln(ans);
39   close(input); close(output);
40 end.

版权所有,转载请联系作者,违者必究

QQ:740929894

原文地址:https://www.cnblogs.com/hadilo/p/5913988.html