题目要求繁杂,需要耐心提炼题目条件。
来源: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; }