poj 1015 Jury Compromise(DP)

题意:

思路:

 

  1 #include<cstring>

  2 #include<iostream>

  3 #include<cmath>

  4 #include<algorithm>

  5 using namespace std;

  6 

  7 int n;  //候选人数

  8 int m;  //当选人数

  9 int dp[21][801];   //dp[j][k]:取j个候选人,使其辩控差为k的所有方案中,辩控和最大的方案的辩控和

 10 int path[21][801];  //记录所选定的候选人的编号

 11 int p[222];  //每个人的控方值

 12 int d[222];  //每个人的辩方值

 13 int s[222];  //每个人的辨控和

 14 int v[222];  //每个人的辨控差

 15 int id[222]; //保存候选人编号

 16 

 17 /*检查dp[j][k]方案是否曾选择过候选人i*/

 18 bool check(int j, int k, int i, int* v)

 19 {

 20     while (j>0 && path[j][k] != i)

 21     {

 22         k -= v[path[j][k]];

 23         j--;

 24     }

 25     return j ? false : true;

 26 }

 27 

 28 void init()

 29 {

 30     memset(dp, -1, sizeof(dp));

 31     memset(path, 0, sizeof(path));

 32     memset(p, 0, sizeof(p));

 33     memset(d, 0, sizeof(d));

 34     memset(s, 0, sizeof(s));

 35     memset(v, 0, sizeof(v));

 36 }

 37 

 38 int main()

 39 {

 40     int time = 1;

 41     while (cin >> n >> m && n)

 42     {

 43         /*Initial*/

 44         int j, k, i;

 45         init();

 46         /*Input*/

 47         for (i = 1; i <= n; i++)

 48         {

 49             cin >> p[i] >> d[i];

 50             s[i] = p[i] + d[i];

 51             v[i] = p[i] - d[i];

 52         }

 53         int fix = m * 20;  //总修正值,修正极限为从[-400,400]映射到[0,800]

 54 

 55         dp[0][fix] = 0;   //由于修正了数值,因此dp[0][fix]才是真正的dp[0][0]

 56         for (j = 1; j <= m; j++)

 57             for (k = 0; k <= 2 * fix; k++) //可能的辩控差为[0,fix*2] 

 58             {

 59                 if (dp[j - 1][k] >= 0)   //区间已平移,dp[0][fix]才是真正的dp[0][0]

 60                 {

 61                     for (i = 1; i <= n; i++)

 62                         if (dp[j][k + v[i]] < dp[j - 1][k] + s[i])

 63                         {

 64                             if (check(j - 1, k, i, v))

 65                             {

 66                                 dp[j][k + v[i]] = dp[j - 1][k] + s[i];

 67                                 path[j][k + v[i]] = i;

 68                             }

 69                         }

 70                 }

 71             }

 72 

 73 

 74         /*Output*/

 75         for (k = 0; k <= fix; k++)

 76             if (dp[m][fix - k] >= 0 || dp[m][fix + k] >= 0)    //从中间向两边搜索最小辨控差的位置k

 77                 break;

 78         int div = dp[m][fix - k] > dp[m][fix + k] ? (fix - k) : (fix + k);  //最小辨控差

 79 

 80         cout << "Jury #" << time++ << endl;

 81         cout << "Best jury has value ";

 82         //辩方总值 = (辨控和+辨控差+修正值)/2

 83         cout << (dp[m][div] + div - fix) / 2 << " for prosecution and value ";

 84         //控方总值 = (辨控和-辨控差+修正值)/2

 85         cout << (dp[m][div] - div + fix) / 2 << " for defence:" << endl;

 86 

 87         for (i = 0, j = m, k = div; i<m; i++)

 88         {

 89             id[i] = path[j][k];

 90             k -= v[id[i]];

 91             j--;

 92         }

 93         sort(id, id + m);   //升序输出候选人编号

 94         for (i = 0; i<m; i++)

 95             cout << ' ' << id[i];

 96         cout << endl << endl;

 97 

 98     }

 99     return 0;

100 }

 

你可能感兴趣的:(Promise)