Jury Compromise(poj 1015)

描述在遥远的国家佛罗布尼亚,嫌犯是否有罪,须由陪审团决定。陪审团是由法官从公众中挑选的。先随机挑选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\n",++Cas);
        printf("Best jury has value %d for prosecution and value %d for defence:\n",(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("\n\n");    
    }
}

 

posted @ 2017-04-18 22:25  karles~  阅读(187)  评论(0编辑  收藏  举报