1015 Jury Compromise

题目要求繁杂,需要耐心提炼题目条件。

来源:https://www.cnblogs.com/YoungNeal/p/8664733.html

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define rg register
#define go(i,a,b) for(rg int i=a;i<=b;i++)
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
int n,m,dp[25][802];
int p[202],d[202],S[202],V[202];
int tag[25][802];
//tag[i][j]表示选了i个人分数为j时第i个人的编号
bool check(int a,int b,int c){//判断c是否被选过
    while(a>0&&c!=tag[a][b]){
        b-=V[tag[a][b]];a--;
    }
    return a;
}
int main(){
    int num=0;
    while(scanf("%d%d",&n,&m)){
        if(n==0&&m==0) break;
        go(i,1,n){
            scanf("%d%d",&p[i],&d[i]);
            S[i]=p[i]+d[i];
            V[i]=p[i]-d[i];
        }
        memset(dp,-1,sizeof(dp));
//dp[i][j]表示选了i个人使分数差值为j的最大和,如不存在则为-1
        memset(tag,0,sizeof(tag));
        int start=20*m;
        dp[0][start]=0;//相当于dp[0][0]
        go(i,1,m) go(j,0,2*start)
            if(dp[i-1][j]!=-1)
                go(k,1,n)
                    if(!check(i-1,j,k)&&dp[i][j+V[k]]<dp[i-1][j]+S[k]){
                        dp[i][j+V[k]]=dp[i-1][j]+S[k];
                        tag[i][j+V[k]]=k;
                    }
        int j;
        for(j=0;j<=start;j++)
            if(dp[m][start-j]!=-1||dp[m][start+j]!=-1) break;
        int sum=dp[m][start-j]>dp[m][start+j]?start-j:start+j;
        int P=(dp[m][sum]+sum-start)/2,D=(dp[m][sum]-sum+start)/2;
        printf("Jury #%d\n",++num);
        printf("Best jury has value %d for prosecution and value %d for defence:\n",P,D);
        int res[25];
        for(rg int i=0,j=m,k=sum;i<m;i++){
            res[i]=tag[j][k];
            k-=V[tag[j][k]];
            j--;
        }
        sort(res,res+m);
        go(i,0,m-1) printf(" %d",res[i]);
        puts("");puts("");
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/sweet-ginger-candy/p/11517282.html