http://poj.org/problem?id=1015
题意:n 个人作为陪审团的候选人,然后再从这n 个人中选m 人组成陪审团,选出的m 个人,必须满足辩方总分D和控方总分P的差的绝对值|D-P|最小。
1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 5 int m,n; 6 int dp[30][805]; 7 int d[300],p[300]; 8 int path[1000][1000]; 9 int ans[30]; 10 11 int cmp(const void *a,const void *b) 12 { 13 return *(int *)a-*(int *)b; 14 } 15 16 int main() 17 { 18 int cnt = 1; 19 while(scanf("%d%d",&n,&m),m||n) 20 { 21 for(int i = 1;i<=n;i++) 22 scanf("%d%d",&d[i],&p[i]); 23 24 int Move = m*20; 25 memset(dp,-1,sizeof(dp)); 26 memset(path,0,sizeof(path)); 27 28 dp[0][Move] = 0; 29 /** 30 DP的部分 31 dp[i][j] 代表i个候选人,相差为j的分数且和最大的那个方案 32 **/ 33 for(int i = 0;i<m;i++) 34 for(int j = 0;j<=Move*2;j++) 35 if(dp[i][j]>=0) 36 { 37 for(int k = 1;k<=n;k++) 38 { 39 if(dp[i][j]+p[k]+d[k]>dp[i+1][j+d[k]-p[k]]) 40 { 41 int t1 = i,t2 = j; 42 //判断是否k这个人用过了 43 while(t1>0&&path[t1][t2]!=k) 44 { 45 t2-=d[path[t1][t2]]-p[path[t1][t2]]; 46 t1--; 47 } 48 if(t1==0) 49 { 50 dp[i+1][j+d[k]-p[k]] = dp[i][j]+p[k]+d[k]; 51 path[i+1][j+d[k]-p[k]] = k; 52 } 53 } 54 } 55 } 56 int tmp = Move,tmp1 = 0; 57 while(dp[m][tmp+tmp1]<0&&dp[m][tmp-tmp1]<0) //找出那个第一个不为-1的,则说明是相差值最小的 58 tmp1++; 59 //用来找那个最小的差 60 if(dp[m][tmp+tmp1]>dp[m][tmp-tmp1]) 61 tmp = tmp+tmp1; 62 else tmp = tmp-tmp1; 63 printf("Jury #%d ",cnt++); 64 printf("Best jury has value %d for prosecution and value %d for defence: ",(tmp-Move+dp[m][tmp])/2,(dp[m][tmp]-tmp+Move)/2); 65 for(int i=1;i<=m;i++) 66 { 67 ans[i]=path[m-i+1][tmp]; 68 tmp-=d[ans[i]]-p[ans[i]]; 69 } 70 qsort(ans+1,m,sizeof(int),cmp); 71 for(int i=1;i<=m;i++) 72 printf(" %d",ans[i]); 73 printf(" "); 74 } 75 return 0; 76 }