[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 \nBest jury has value %d for prosecution and value %d for defence: \n",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("");
    }
}

 

posted @ 2018-03-28 16:42  YoungNeal  阅读(244)  评论(0编辑  收藏  举报