$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$
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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\n",++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:\n",(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("\n\n"); 50 } 51 return 0; 52 }
光伴随的阴影