• $POJ1015 Jury Compromise Dp$/背包


     洛谷传送门

    $Sol$

    这是一道具有多个“体积维度”的$0/1$背包问题。

    把$N$个候选人看做$N$个物品,那么每个物品有如下三种体积:

    1.“人数”,每个候选人的“人数”都是$1$,最终要填满容积为$M$的背包

    2.“辩方得分”,$a[i]$

    3.“反方得分”,$b[i]$

    要求的是辩方总分$D$和控方总分$P$的差的绝对值$|D-P|$最小,如果选择方法不唯一,那么在从中选择$D+P$最大的方案

    所以将$a[i]-b[i]$作为体积之一,将$a[i]+b[i]$作为该物品的价值

    注意这里的$a[i]-b[i]$可能为负,所以统一加上$4000$

    以考虑到第$i$个人为阶段,$f[j][k]$表示已经在前$i$个人中选择了$j$个人,此时两方的总分之差为$k$时,两方的总分最大值。

    $f[j][k]=max(f[j][k],f[j-1][k-(a[i]-b[i])]+a[i]+b[i])$

    由于还需要输出方案,所以再加一个数组$d[i][j][k]$表示$f[i][j][k]$的第$i$个候选人选没选,这样就记录了方案。

    $Code$

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #define Rg register
     5 #define il inline
     6 #define mem(a,b) memset(a,b,sizeof(a));
     7 #define go(i,a,b) for(Rg int i=a;i<=b;i++)
     8 #define yes(i,a,b) for(Rg int i=a;i>=b;i--)
     9 using namespace std;
    10 il int read()
    11 {
    12     int x=0,y=1;char c=getchar();
    13     while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();}
    14     while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+c-'0';c=getchar();}
    15     return x*y;
    16 }
    17 int T,n,m,hhh=400,t,ct,a[201],b[201],f[21][801],as[21];
    18 bool d[201][21][801];
    19 int main()
    20 {
    21     while(1)
    22     {
    23         n=read(),m=read();if(!n)break;
    24         printf("Jury #%d
    ",++T);
    25         go(i,1,n)a[i]=read(),b[i]=read();
    26         mem(f,-777);mem(d,0);
    27         f[0][hhh]=0;
    28         go(i,1,n)
    29             yes(j,m,1)
    30             go(k,-400,400)
    31                 {
    32                     if(k-(a[i]-b[i])>=-400 && k-(a[i]-b[i])<=400 && f[j-1][k-(a[i]-b[i])+hhh]+a[i]+b[i]>=0 && f[j][k+hhh]<f[j-1][k-(a[i]-b[i])+hhh]+a[i]+b[i])
    33                         f[j][k+hhh]=f[j-1][k-(a[i]-b[i])+hhh]+a[i]+b[i],d[i][j][k+hhh]=1;
    34                     //if(f[j][k+hhh]>=0)cout<<"i:"<<i<<" j:"<<j<<" k:"<<k<<" f:"<<f[j][k+hhh]<<" d:"<<d[i][j][k+hhh]<<endl;
    35                 }
    36         go(i,0,400)
    37         {
    38             if(f[m][hhh+i]>=0){if(f[m][hhh+i]>f[m][hhh-i])t=i;else t=-i;break;}
    39             else if(f[m][hhh-i]>=0){t=-i;break;}
    40         }
    41         printf("Best jury has value %d for prosecution and value %d for defence:
    ",(f[m][hhh+t]+t)/2,(f[m][hhh+t]-t)/2);
    42         int nw=n;ct=m;
    43         while(nw>0)
    44         {
    45             int dd=d[nw][ct][t+hhh];
    46             if(dd)as[ct]=nw,ct--,t-=(a[nw]-b[nw]);
    47             nw--;
    48         }
    49         go(i,1,m)printf(" %d",as[i]);printf("
    
    ");
    50     }
    51     return 0;
    52 }
    View Code
    光伴随的阴影
  • 相关阅读:
    UVA 11021繁衍模型+概率计算
    LA 5059博弈+SG函数
    LA 3942 字典树
    Beat---hdu2614
    Wooden Sticks---hdu1051(最长上升子序列)
    欧拉函数基础
    1370
    钱币兑换问题---hdu1284(完全背包)
    Drainage Ditches--hdu1532(网络流 模板)
    Fibonacci--poj3070(矩阵快速幂)
  • 原文地址:https://www.cnblogs.com/forward777/p/10993789.html
Copyright © 2020-2023  润新知