描述在遥远的国家佛罗布尼亚,嫌犯是否有罪,须由陪审团决定。陪审团是由法官从公众中挑选的。先随机挑选n个人作为陪审团的候选人,然后再从这n个人中选m人组成陪审团。选m人的办法是:
控方和辩方会根据对候选人的喜欢程度,给所有候选人打分,分值从0到20。为了公平起见,法官选出陪审团的原则是:选出的m个人,必须满足辩方总分和控方总分的差的绝对值最小。如果有多种选择方案的辩方总分和控方总分的之差的绝对值相同,那么选辩控双方总分之和最大的方案即可。输入输入包含多组数据。每组数据的第一行是两个整数n和m,n是候选人数目,m是陪审团人数。注意,1<=n<=200, 1<=m<=20 而且 m<=n。接下来的n行,每行表示一个候选人的信息,它包含2个整数,先后是控方和辩方对该候选人的打分。候选人按出现的先后从1开始编号。两组有效数据之间以空行分隔。最后一组数据n=m=0输出对每组数据,先输出一行,表示答案所属的组号,如 'Jury #1', 'Jury #2', 等。接下来的一行要象例子那样输出陪审团的控方总分和辩方总分。再下来一行要以升序输出陪审团里每个成员的编号,两个成员编号之间用空格分隔。每组输出数据须以一个空行结束。样例输入
4 2 1 2 2 3 4 1 6 2 0 0
样例输出
Jury #1 Best jury has value 6 for prosecution and value 4 for defence: 2 3
/* 自己写了一个三维状态的f[i][j][k]表示前i个选了j个,相差k的最大值,但是无奈怎么也过不去。 题解设的是二维的,把第一位去掉了,转移比较巧妙。 */ #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define N 310 #define M 1010 using namespace std; int f[N][M],pa[N][M];; int a[N],b[N],Answer[N],n,m,Cas; int main(){ while(scanf("%d%d",&n,&m)){ if(n==0&&m==0) break; for(int i=1;i<=n;i++) scanf("%d%d",&a[i],&b[i]); memset(f,-1,sizeof(f)); memset(pa,0,sizeof(pa)); int base=m*20; f[0][base]=0; for(int j=0;j<m;j++) for(int k=0;k<=base*2;k++) if(f[j][k]>=0){ for(int i=1;i<=n;i++) if(f[j][k]+a[i]+b[i]>f[j+1][k+a[i]-b[i]]){ int t1=j,t2=k; while(t1>0&&pa[t1][t2]!=i){ t2-=a[pa[t1][t2]]-b[pa[t1][t2]]; t1--; } if(t1==0){ f[j+1][k+a[i]-b[i]]=f[j][k]+a[i]+b[i]; pa[j+1][k+a[i]-b[i]]=i; } } } int i=base,j=0,k; while(f[m][i+j]<0&&f[m][i-j]<0) j++; if(f[m][i+j]>f[m][i-j]) k=i+j; else k=i-j; printf("Jury #%d ",++Cas); printf("Best jury has value %d for prosecution and value %d for defence: ",(k-base+f[m][k])/2,(f[m][k]-k+base)/2); for(i=1;i<=m;i++) { Answer[i]=pa[m-i+1][k]; k-=a[Answer[i]]-b[Answer[i]]; } sort(Answer+1,Answer+m+1); for(i=1;i<=m;i++) printf(" %d",Answer[i]); printf(" "); } }