POJ 1015--Jury Compromise

来源:互联网 发布:死亡之翼的背脊数据库 编辑:程序博客网 时间:2024/04/29 08:50

        题目大意:在遥远的国家佛罗布尼亚,嫌犯由陪审团决定是否有罪。先随机挑选n个人作为陪审团的候选人,然后再从这n个人中选m人组成陪审团。控方和辩方会给所有候选人打分,分值从0到20(分数越高代表越喜欢)。为了公平起见,选出的m个人必须满足辩方总分和控方总分之差的绝对值最小。如果出现多种方案,那么选辩控双方总分之和最大的方案即可。

    比较容易想到的就是动态规划,先对候选人进行排序,由于评分差为-20到20,将评分差加上20,变为0到40。用一个二维数组表示选中的第几号人v[index][value],  假定评分数组为diff[] = {10, 20, 23, 29...},比如v[1][20]==2,代表选第一个人时,评分为20时,选中了第2号人。以此类推v[2][43]==3,这样可以得到一个完整的选择链(想要知道前一个人的选择,只需求v[2 - 1][43 - diff[3]] = v[1][20] = 2)。

    最后,假定需要选择10个人,若v[10][400] != 0,那么v[10][400]下面的选择链便是最优解。反之搜索最靠近v[10][400]的情况即可。比如当v[10][390] != 0 && v[10][405] != 0,那么v[10][405]必定优于v[10][390]。事实上,这种方法会有重复计算的情况,再加优化的话,100MS内应该没什么问题。附上代码:

    Memory: 328K        Time: 250MS       Length:154Lines

#include<iostream>#include<cstring>using namespace std;struct JURY                           //陪审员{int count;                    //原始编号int pi;int di;};int v[21][801] = {};JURY pJury[200];inline int inline_sum(JURY& j) { return j.di + j.pi; }inline int inline_diff(JURY& j) { return j.pi - j.di + 20; }void Sort_Insert(const int c)          //插入排序{for (int i = 1; i < c; ++i){JURY temp = pJury[i];int j = i;while (j > 0)if (inline_diff(temp) < inline_diff(pJury[j - 1])){pJury[j] = pJury[j - 1];--j;}elsebreak;pJury[j] = temp;}}void Find_min_max(const int c, int count, int& minval, int& maxval)  //计算前后count个候选人辨控差的和{for (int i = 0; i < count; ++i){minval += inline_diff(pJury[i]);maxval += inline_diff(pJury[c - 1 - i]);}}int Update(int depth, int value, int tmpvalue)                    //更新选择链{int cu = 0;int pen = 0;while (depth > 0){cu += inline_sum(pJury[v[depth][value]]);pen += inline_sum(pJury[v[depth][tmpvalue]]);value -= inline_diff(pJury[v[depth][value]]);tmpvalue -= inline_diff(pJury[v[depth][tmpvalue]]);--depth;}return pen - cu;}bool find_pos(int depth, int value, int k)                    //在一个选择链上查找某个候选人是否已经存在{while (depth > 0){if (v[depth][value] == k)return true;value -= inline_diff(pJury[v[depth][value]]);--depth;}return false;}inline int inline_max(int a, int b) { return inline_sum(pJury[a]) > inline_sum(pJury[b]) ? a : b; }int main(){int candidates = 0;int members = 0;int count = 0;while (cin >> candidates >> members && candidates != 0 && members != 0){int selected[200] = {};memset(&v, -1, sizeof(v));for (int i = 0; i < candidates; ++i){cin >> pJury[i].pi >> pJury[i].di;pJury[i].count = i;}Sort_Insert(candidates);for (int j = 1; j <= members; ++j){int maxval = 0;int minval = 0;Find_min_max(candidates, j, minval, maxval);for (int i = minval; i <= maxval; ++i){for (int k = 0; k < candidates - members + j; ++k){if (i < inline_diff(pJury[k]));else if (i == inline_diff(pJury[k]) && j == 1)v[j][i] = v[j][i] != -1 ? inline_max(v[j][i], k) : k;else if (v[j - 1][i - inline_diff(pJury[k])] != -1){if (v[j][i] == -1) //无值时,先搜索是否已存在{if (!find_pos(j - 1, i - inline_diff(pJury[k]), k))v[j][i] = k;}else     //有值时,先搜索,再比较{if (!find_pos(j - 1, i - inline_diff(pJury[k]), k))if (inline_sum(pJury[k]) - inline_sum(pJury[v[j][i]]) + Update(j - 1, i - inline_diff(pJury[v[j][i]]), i - inline_diff(pJury[k])) > 0)v[j][i] = k;}}}}}int v1, v2, val;val = v1 = v2 = members * 20;if (v[members][v1] == -1)              //寻找最优解{while (v1 <= members * 40){++v1;--v2;if (v[members][v1] == -1 && v[members][v2] != -1){val = v2;break;}else if (v[members][v1] != -1 && v[members][v2] == -1){val = v1;break;}else if (v[members][v1] != -1 && v[members][v2] != -1){if (inline_sum(pJury[v[members][v1]]) - inline_sum(pJury[v[members][v2]]) + Update(members - 1, v2 - inline_diff(pJury[v[members][v2]]), v1 - inline_diff(pJury[v[members][v1]])) > 0)val = v1;elseval = v2;break;}}}int sum_pi = 0;int sum_di = 0;for (int i = members; i > 0; --i){selected[pJury[v[i][val]].count] = 1;sum_pi += pJury[v[i][val]].pi;sum_di += pJury[v[i][val]].di;val -= inline_diff(pJury[v[i][val]]);}cout << "Jury #" << ++count << endl;cout << "Best jury has value " << sum_pi << " for prosecution and value " << sum_di << " for defence:" << endl;int mm = 0;for (int i = 0; i < candidates && mm < members; ++i)if (selected[i]){cout << " " << i + 1;++mm;}cout << endl << endl;}return 0;}


0 0
原创粉丝点击