• [POJ 1015] Jury Compromise


    Description

    在遥远的国家佛罗布尼亚,嫌犯是否有罪,须由陪审团决定。陪审团是由法官从公众中挑选的。先随机挑选n 个人作为陪审团的候选人,然后再从这n 个人中选m 人组成陪审团。选m 人的办法是:控方和辩方会根据对候选人的喜欢程度,给所有候选人打分,分值从0 到20。为了公平起见,法官选出陪审团的原则是:选出的m 个人,必须满足辩方总分D控方总分P的差的绝对值|D-P|最小。如果有多种选择方案的 |D-P| 值相同,那么选辩控双方总分之和D+P最大的方案即可。

    Output

    选取符合条件的最优m个候选人后,要求输出这m个人的辩方总值D和控方总值P,并升序输出他们的编号。

    Solution

    dp 比较好想,难的是记录路径。

    (来自颜神犇的奇技淫巧)

    定义路径数组 path[i][j][k] 表示经过 i 个人,选了 j 个人,差值为 k 的状态最后一个选的是谁。

    转移的时候让 path[i][j][k]=path[i-1][j][k] 就好

    最后输出的时候要这样

    int nnow=n;
    for(int k=m;k;k--){
        int now=per[nnow][k][idx];
        a+=p[now];
        b+=d[now];
        idx-=cha[now];
        nnow=now-1; // 这里要减一是因为转移的时候是从 i-1 转移来的
        ans[++ans[0]]=now;
    }

    Code

    // By YoungNeal
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    
    int n,m,T;
    int ans[805];
    int cha[205];
    int f[25][1005];
    int p[205],d[205];
    int per[205][25][1005];
    
    void clear(){
        memset(p,0,sizeof p);
        memset(d,0,sizeof d);
        memset(f,0xcf,sizeof f);
        memset(ans,0,sizeof ans);
        memset(cha,0,sizeof cha);
        memset(per,0,sizeof per);
    }
    
    signed main(){
        while(scanf("%d%d",&n,&m)){
            if(n+m==0) return 0;
            clear();
            T++;
            for(int i=1;i<=n;i++){
                scanf("%d%d",&p[i],&d[i]);
                cha[i]=p[i]-d[i];
            }
            f[0][400]=0;
            //per[0][0][400]=1;
            for(int i=1;i<=n;i++){
                for(int k=m;k;k--){
                    for(int j=800;j>=cha[i];j--){
                        per[i][k][j]=per[i-1][k][j];
                        if(f[k-1][j-cha[i]]<0) continue;
                        if(f[k][j]<f[k-1][j-cha[i]]+d[i]+p[i]){
                            f[k][j]=f[k-1][j-cha[i]]+d[i]+p[i];
                            per[i][k][j]=i;
                        }
                    }
                }
            }
            int idx;
            for(int i=0;i<=400;i++){
                if(f[m][400+i]!=0xcfcfcfcf||f[m][400-i]!=0xcfcfcfcf){
                    idx=(f[m][400+i]>=f[m][400-i]?400+i:400-i); 
                    break;
                }
            }
            int a=0,b=0;ans[0]=0;
            int nnow=n;
            for(int k=m;k;k--){
                int now=per[nnow][k][idx];
                a+=p[now];
                b+=d[now];
                idx-=cha[now];
                nnow=now-1;
                ans[++ans[0]]=now;
            }
            printf("Jury #%d 
    Best jury has value %d for prosecution and value %d for defence: 
    ",T,a,b);
            std::sort(ans+1,ans+1+ans[0]);
            for(int i=1;i<=ans[0];i++) printf(" %d",ans[i]);printf(" ");
            puts(""),puts("");
        }
    }
  • 相关阅读:
    Vue2.0一个login跳转实例
    canvas动画—圆形扩散、运动轨迹
    根据地理信息绘画的html5 小游戏
    用vue开发一个猫眼电影web app
    微信小程序 iphone6 和 iphone6plus 如何设置rpx单位,通俗易懂的方法
    前端实例练习
    为表单加上即时通讯的能力
    MongoDB学习笔记4——GridFS基础
    剑指Offer(Java版)第十三题:请实现一个函数,输入一个整数,输出该数二进制表示中1的个数。
    剑指Offer(Java版)第十一题
  • 原文地址:https://www.cnblogs.com/YoungNeal/p/8664733.html
Copyright © 2020-2023  润新知