POJ 1015--Jury Compromise
2017-07-06 23:21
387 查看
题意
题目大意是讲,在遥远的国家佛罗布尼亚,嫌犯由陪审团决定是否有罪。先随机挑选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; } else break; 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; else val = 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; }
相关文章推荐
- K - Jury Compromise POJ 1015 (动态规划 --难)
- [POJ][1015]Jury Compromise
- POJ1015 Jury Compromise dfs的实现
- poj Jury Compromise 1015 (DP) 好题
- POJ 1015 Jury Compromise dp
- poj Jury Compromise
- pku 1015 Jury Compromise DP
- poj 1015 Jury Compromise
- POJ 1015 Jury Compromise
- POJ1015 - Jury Compromise(DP+计算顺序)
- POJ-1015
- POJ 1015
- POJ 2250 Compromise(文章的最长公共子序列LCS)
- poj 1015 Jury Compromise
- POJ 1015 陪审团人选 [动态规划]
- POJ 1248 && HDU 1015 Safecracker(dfs)
- poj1015 Jury Compromise
- POJ 2250 Compromise (UVA 531)
- POJ 1015 Jury Compromise(DP+回溯)
- POJ 1015 Jury Compromise dp分组