POJ1015-Jury Compromise-dp

略复杂的dp题。

有n个人,每个人有两个分数di,pi。从中选出m个人,要求|sigma(di)-sigma(pi)|最小,相同时则输出sigma(di)+sigma(pi)最大的情况。

答案完整输出方案。

 

dp[i][j]表示i个人的组合里,差值为j的情况下,和值的最大值。

计算每一个人的差值subi,和值sumi

则dp[i][j] = max(dp[i-1][j-subk]+sumk) k∈n

注意dp的时候为了能表示负数,要加一个修正值。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 
 5 using namespace std;
 6 
 7 const int maxn = 200+10;
 8 const int X = 500;
 9 const int INF = 0x3f3f3f3f;
10 
11 int n,m;
12 int sum[maxn],sub[maxn];
13 int dp[25][10*maxn];
14 int path[25][10*maxn];
15 
16 bool check(int i,int j,int k)
17 {
18     int tmp ;
19     while(path[i][X+j])
20     {
21         tmp = path[i][X+j];
22         if(k == tmp)
23             return false;
24         j -= sub[tmp];
25         i--;
26     }
27     return true;
28 }
29 
30 int main()
31 {
32     int cas = 0;
33     while(scanf("%d%d",&n,&m) && n)
34     {
35         int d,p;
36         cas++;
37         for(int i=1;i<=n;i++)
38         {
39             scanf("%d%d",&p,&d);
40             sum[i] = p+d;
41             sub[i] = p-d;
42         }
43         memset(dp,-1,sizeof dp);
44         memset(path,0,sizeof path);
45 
46         dp[0][X+0] = 0;
47 
48         int ans_sub = 400+5;
49         for(int i=1;i<=m;i++)
50         {
51             for(int j=-400;j<=400;j++)
52             {
53                 for(int k=1;k<=n;k++)if(dp[i-1][X+j-sub[k]] != -1 && check(i-1,j-sub[k],k))
54                 {
55                     if(dp[i-1][X+j-sub[k]]+sum[k] > dp[i][X+j])
56                     {
57                         dp[i][X+j] = dp[i-1][X+j-sub[k]]+sum[k];
58                         path[i][X+j] = k;
59                         //printf("i:%d j:%d k:%d dp:%d\n",i,j,k,dp[i][X+j]);
60                         if(i==m && ( abs(j) < abs(ans_sub) || (abs(j)==abs(ans_sub) && dp[i][X+j] > dp[i][X+ans_sub]) ) )
61                         {
62                             ans_sub = j;
63                         }
64                     }
65                 }
66             }
67         }
68 
69         //printf("%d\n",ans_sub);
70         printf("Jury #%d\n",cas);
71         printf("Best jury has value %d for prosecution and value %d for defence: \n",(dp[m][X+ans_sub]+ans_sub)/2,(dp[m][X+ans_sub]-ans_sub)/2);
72 
73         int ans[25],cnt=0;
74         for(int i=m;i>=1;i--)
75         {
76             ans[cnt++] = path[i][X+ans_sub];
77             ans_sub -= sub[ans[cnt-1]];
78         }
79         sort(ans,ans+cnt);
80 
81         for(int i=0;i<cnt;i++)
82         {
83             printf(" %d",ans[i]);
84         }
85         printf("\n\n");
86     }
87 }

最近dp写的略顺手

posted @ 2016-05-28 18:02  Helica  阅读(175)  评论(0编辑  收藏  举报