zoukankan      html  css  js  c++  java
  • [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("");
        }
    }
  • 相关阅读:
    经典网页设计:漂亮的个人作品集网站设计欣赏【中篇】
    引领网页设计潮流的优秀网页作品赏析《第二季》
    Chance – 功能强大的 JavaScript 随机数生成类库
    设计前沿:16款扁平风格 iOS 7 图标设计
    TwentyTwenty – 使用 jQuery 实现图片对比功能
    未来的 Web:九个不可思议的 WebGL 应用试验
    推荐25个帮助你提高技能的 CSS3 实战教程
    经典网页设计:顶尖的个人作品集网站设计欣赏【上篇】
    Smint – 用于单页网站制作的 jQuery 导航菜单插件
    关注经典:CSS Awards 获奖网站作品赏析《第一季》
  • 原文地址:https://www.cnblogs.com/YoungNeal/p/8664733.html
Copyright © 2011-2022 走看看