题目来源:http://poj.org/problem?id=1015
解题报告:
f[i][j]: 代表i个人,sum(DJ) - sum(PJ)为j-400 的组合中,最大的sum(DJ) + sum(PJ)值
path[i][j]:代表路径中的最后一人的编号。
d[k] = Dj[k] - Pj[k]
s[k] = Dj[k] + Pj[k]
那么有递推式:
f[i][j + d[k]] = max(f[i][j + d[k]], f[i-1][j] + s[k])
还要保证K没有出现在f[i-1][j]之前的路径中,这个可以通过
pre = path[i-1][j]
path[i-2][j-d[pre]]这样依次向前查找。
如果f[i][j + d[k]]的值更新了,则同时要更新path[i][j + d[k]] = k。
最后根据f[][]的值,从400开始向两边搜索,找到有值的f[i][j],然后根据path[i][j]依次向前获得总路径,用sort()排序,输出结果。
#include <iostream> #include <vector> #include <algorithm> #include <string> using namespace std; #define abs(a) ((a)>0?(a):(-a)) #define INFINITE -100000 int path[21][802]; int f[21][802]; int main() { int m, n; int caseNum=1; while(1) { cin >> n; cin >> m; if(m==0 && n==0) break; int *di=new int [n]; int *pi=new int [n]; int *s = new int[n]; int *d = new int[n]; for(int i=0;i<n;i++) { cin >> di[i] >> pi[i]; s[i] = di[i] + pi[i]; d[i] = di[i] - pi[i]; } for (int i = 0; i <= 20; i++) { for (int j = 0; j <= 800; j ++) { f[i][j] = INFINITE; path[i][j] = -1; } } for (int k = 0; k < n; k++) { if (f[1][d[k]+400] < s[k]) //一开始这里没判断,WA了很多次 { f[1][d[k] + 400] = s[k]; path[1][d[k] + 400] = k; } } for (int i = 1; i < m; i++) { for (int j = 0; j <= 800; j++) { if (f[i][j] >= 0) { for (int k = 0; k < n; k++) { bool existed = false; if (path[i][j] == k) continue; int pre = path[i][j]; int begin = j; for (int l = i-1; l >= 1; l--) { begin = begin - d[pre]; pre = path[l][begin]; if(pre == k) { existed = true; break; } } if (!existed) { if (f[i+1][j+d[k]] < f[i][j] + s[k]) { f[i+1][j+d[k]] = f[i][j] + s[k]; path[i+1][j+d[k]] = k; } } } } } } int begin; for (int i = 0; i <= 400; i++) { if (f[m][400-i] != INFINITE || f[m][400+i] != INFINITE) { if ( f[m][400-i] < f[m][400+i] ) begin = 400 + i; else begin = 400 - i; break; } } vector<int> finalPath; int pro = 0; int def = 0; int pre = path[m][begin]; for (int i = 0; i < m; i++) { finalPath.push_back(pre); pro += di[pre]; def += pi[pre]; begin = begin - d[pre]; pre = path[m-i-1][begin]; } cout << "Jury #" << caseNum++ << endl; cout << "Best jury has value " << pro << " for prosecution and value " << def << " for defence:" << endl; sort(finalPath.begin(), finalPath.end()); for (int i = 0; i < finalPath.size(); i++) { cout << " " << finalPath[i] + 1; } cout << endl; delete[] di; delete[] pi; delete[] s; delete[] d; } }
Time Limit: 1000MS | Memory Limit: 65536K | |||
Total Submissions: 21381 | Accepted: 5458 | Special Judge |
Description
Input
Output
Sample Input
4 2 1 2 2 3 4 1 6 2 0 0
Sample Output
Jury #1 Best jury has value 6 for prosecution and value 4 for defence: 2 3
Hint