• 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
    ",++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("
    
    ");    
        }
    }
  • 相关阅读:
    第五十六课 树中结点的删除操作
    第五十五课 树中节点的清除操作
    常用的机器学习&数据挖掘知识点总结
    leetcode 211. Add and Search Word
    leetcode 349. Intersection of Two Arrays
    leetcode 659. Split Array into Consecutive Subsequences
    leetcode 658. Find K Closest Elements
    leetcode 657. Judge Route Circle
    leetcode 179. Largest Number
    leetcode 660. Remove 9
  • 原文地址:https://www.cnblogs.com/harden/p/6730903.html
Copyright © 2020-2023  润新知