题意:审判囚犯了,要在n选择m个人组成陪审团,每个人对那个囚犯有一个好感值,厌恶值。为了保证审判,陪审团要保证公正,所以在保证所有人的好感值和与厌恶值和的差值最小,然后确保好感值和厌恶值和的总值最大。
做法:记录的状态是当前好感值和厌恶值的差值,当前好感值的和与厌恶值的和,DFS求出选择方案。o(︶︿︶)o 唉,最后取答案的之后,竟然把n写成了i,wa多次
#include<cstdio> #include<cstring> const int LMT=202; const int offset=400; int dp[2][25][805][2]; bool vis[LMT][25][805]; struct jury { int d,p; }ju[LMT]; inline int max(int a,int b) { return a>b?a:b; } inline int min(int a,int b) { return a<b?a:b; } void init(void) { memset(dp,-1,sizeof(dp)); memset(vis,0,sizeof(vis)); dp[0][0][offset][0]=dp[0][0][offset][1]=0; ju[0].d=ju[0].p=0; } inline int abs(int x) { return x>0?x:-x; } void dfs(int i,int j,int k) { if(i<=0)return; if(vis[i][j][k]) { dfs(i-1,j-1,k-ju[i].d+ju[i].p); printf(" %d",i); } else dfs(i-1,j,k); } int main(void ) { int i,j,di,n,m,ans,ansm,x,dm,pm,use,I=1; while(~scanf("%d%d",&n,&m)&&(m||n)) { init(); ans=100000000; ansm=0;dm=pm=0; for(i=1;i<=n;i++) scanf("%d%d",&ju[i].p,&ju[i].d); for(i=1;i<=n;i++) { dp[i&1][0][offset][1]=dp[i&1][0][offset][0]=0; for(di=offset<<1;di>=0;di--) { x=di-ju[i].d+ju[i].p; for(j=m;j>0;j--) { if(x>=0&&x<=offset<<1&&dp[(i-1)&1][j-1][x][0]!=-1) { if(dp[(i-1)&1][j-1][x][0]+ju[i].d+ju[i].p +dp[(i-1)&1][j-1][x][1] >dp[i&1][j][di][0]+dp[i&1][j][di][1]) { dp[i&1][j][di][0]=dp[(i-1)&1][j-1][x][0]+ju[i].d; dp[i&1][j][di][1]=dp[(i-1)&1][j-1][x][1]+ju[i].p; vis[i][j][di]=1; } } if(dp[(i-1)&1][j][di][0]+dp[(i-1)&1][j][di][1] >dp[i&1][j][di][0]+dp[i&1][j][di][1]) { vis[i][j][di]=0; dp[i&1][j][di][0]=dp[(i-1)&1][j][di][0]; dp[i&1][j][di][1]=dp[(i-1)&1][j][di][1]; } } } } for(di=0;di<=offset<<1;di++) if(dp[n&1][m][di][0]!=-1&&ans>abs(di-offset)) { ans=abs(di-offset); use=di-offset; ansm=dp[n&1][m][di][0]+dp[n&1][m][di][1]; } else if(ans==abs(di-offset)&&ansm<dp[n&1][m][di][0]+dp[n&1][m][di][1]) { ansm=dp[n&1][m][di][0]+dp[n&1][m][di][1]; use=di-offset; } printf("Jury #%d\n",I++); printf("Best jury has value %d for prosecution and value %d for defence:\n", dp[n&1][m][use+offset][1],dp[n&1][m][use+offset][0]); dfs(n,m,use+offset); printf("\n"); } return 0; }