POJ1015-Jury Compromise

题意:给你n个数对(d, p),挑选出m个,使得sigma(d)sigma(p)的差最小,如果有多种选法,选sigma(d)+sigma(p)最大的

dp(i,j)表示选出i个人,差值为jsigma(d)+sigma(p)的最大值,初始为-1,那么最后的答案就是使dp(m,j)>=0j的最小值。那么如何求dp(i,j)呢?肯定是在选出m-1个人的基础上再选一个人。设是在dp(i-1,x)的基础上选出的,那么必须要存在一个数对满足x+d-p=j且这个数对没有在dp(i-1,x)方案中出现过。那么如何知道有没有出现过呢?可以用数组path[i][j]表示方案dp(i,j)dp(i-1,x)基础上再选出的那个人的编号。所以可以从path[i][j]往回寻找方案中所有已经被选过的人,排除即可。最后需要注意的就是差值会小于0,给它加上一个修正值fix,变成非负数就行了。

 1 #include <iostream>
 2 #include <sstream>
 3 #include <fstream>
 4 #include <string>
 5 #include <map>
 6 #include <vector>
 7 #include <list>
 8 #include <set>
 9 #include <stack>
10 #include <queue>
11 #include <deque>
12 #include <algorithm>
13 #include <functional>
14 #include <numeric>
15 #include <iomanip>
16 #include <climits>
17 #include <new>
18 #include <utility>
19 #include <iterator>
20 #include <complex>
21 #include <cstdio>
22 #include <cstdlib>
23 #include <cstring>
24 #include <cctype>
25 #include <cmath>
26 #include <ctime>
27 using namespace std;
28 
29 const int maxn = 210;
30 const int maxm = 25;
31 const int fix = 400;
32 
33 int n, m;
34 int d[maxn], p[maxn];
35 int dp[maxm][2*fix+10];
36 int path[maxm][2*fix+10];
37 int ans[maxm];
38 
39 int main()
40 {
41     int kase = 1;
42     while (scanf("%d%d", &n, &m) == 2 && (n || m))
43     {
44         for (int i = 0; i < n; ++i)
45             scanf("%d%d", &d[i], &p[i]);
46         memset(dp, -1, sizeof(dp));
47         memset(path, 0, sizeof(path));
48         dp[0][fix] = 0;
49         for (int i = 0; i < m; ++i)
50             for (int j = 0; j < 2*fix+10; ++j)
51                 if (dp[i][j] >= 0)
52                     for (int k = 0; k < n; ++k)
53                         if (dp[i][j]+d[k]+p[k] > dp[i+1][j+d[k]-p[k]])
54                         {
55                             int ti = i, tj = j;
56                             while (ti > 0 && path[ti][tj] != k)
57                             {
58                                 tj -= d[path[ti][tj]] - p[path[ti][tj]];
59                                 ti--;
60                             }
61                             if (!ti)
62                             {
63                                 dp[i+1][j+d[k]-p[k]] = dp[i][j] + d[k] + p[k];
64                                 path[i+1][j+d[k]-p[k]] = k;
65                             }
66                         }
67         int dj = 0;
68         while (dp[m][fix-dj] == -1 && dp[m][fix+dj] == -1)
69             dj++;
70         int k = dp[m][fix-dj] > dp[m][fix+dj] ? fix-dj : fix+dj;
71         printf("Jury #%d
", kase++);
72         printf("Best jury has value %d for prosecution and value %d for defence:
", (k-fix+dp[m][k])/2, (dp[m][k]-k+fix)/2);
73         for (int i = 0; i < m; ++i)
74         {
75             ans[i] = path[m-i][k];
76             k -= d[ans[i]] - p[ans[i]];
77         }
78         sort(ans, ans+m);
79         for (int i = 0; i < m; ++i)
80             printf("%d%c", ans[i]+1, i==m-1?'
':' ');
81     }
82     return 0;
83 }
原文地址:https://www.cnblogs.com/godweiyang/p/4913868.html