• 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

  • 相关阅读:
    POJ 2253 Frogger(最短路 Floyd)
    POJ 1062 昂贵的聘礼 (最短路 Dijkstra)
    POJ 3259 Wormholes(最短路Bellman_Ford)
    POJ 3414 Pots(容量BFS)
    POJ 3087 Shuffle'm Up(模拟题)
    POJ 3216 Prime Path(数字BFS)
    refresh的停车场
    基于邻接表的广度优先搜索遍历
    判断给定图是否存在合法的拓扑排序
    威威猫系列故事——篮球梦
  • 原文地址:https://www.cnblogs.com/hadilo/p/5913988.html
Copyright © 2020-2023  润新知