pku1015Jury Compromise
n组数字,每组两个数字 d 和 p,要求从中选出m组,使(m个d的和)与(m个p的和)之差最大,如果有种情况的差值相同,取所有d,p总和最大的那种情况。
参考
#include<iostream> #include<string.h> #include<algorithm> using namespace std; int dp[21][801],path[21][801],v[201],s[201],list[21]; bool select(int j,int k,int i) { while(j>0 && path[j][k]!=i) { k-=v[ path[j][k] ]; j--; } return j?1:0; } int main() { int T=1,n,m,i,j,k,d,p,fix; while(scanf("%d%d",&n,&m),n+m) { memset(dp,-1,sizeof(dp));memset(path,0,sizeof(path)); fix=m*20;dp[0][fix]=0; for(i=1;i<=n;i++) { scanf("%d%d",&d,&p); v[i]=d-p;s[i]=d+p; } for(j=1;j<=m;j++) for(k=0;k<=2*fix;k++) if(dp[j-1][k]>=0) for(i=1;i<=n;i++) if(dp[j][k+v[i]]<dp[j-1][k]+s[i]) if(!select(j-1,k,i)) { dp[j][k+v[i]]=dp[j-1][k]+s[i]; path[j][k+v[i]]=i; } // for(i=1;i<=m;i++) printf("!%d ",list[i]);printf("\npath\n"); for(k=0;k<=fix;k++) if(dp[m][fix-k]>=0||dp[m][fix+k]>=0) break; d=dp[m][fix-k]>dp[m][fix+k]?fix-k:fix+k; for(p=d,i=1;i<=m;i++) { list[i]=path[m-i+1][p]; p-=v[list[i]]; } sort(list+1,list+m+1); printf("Jury #%d\n",T++); printf("Best jury has value %d for prosecution and value %d for defence:\n",(dp[m][d]+d-fix)/2,(dp[m][d]-d+fix)/2); for(i=1;i<=m;i++) printf(" %d",list[i]);printf("\n\n"); } return 0; } /* 4 2 1 2 2 3 4 1 6 2 Jury #1 Best jury has value 6 for prosecution and value 4 for defence: 2 3 */