(Click here to view the original title)
The meaning of problems
In order to judge an individual, need to be elected in n m individual among individuals jury, n individuals each person has a value of p prosecution and the defense as a value d, in order to ensure fairness, as the prosecution of individuals requires m square value sum value as the sum of P and D meet defense | PD | minimum, on this basis, requiring maximum P + D. Finally seeking P, D as well as the individual selected jury m and the m individual lexicographically smallest.
Problem-solving ideas
After understand the subject, it is easy to find a backpack that is the question of whether person i choose as a jury, but the number of people selected must be of m, compared to the 01 knapsack problem, this problem limits the number of people selected , then we use DP [j] [j] i represents the current selected individual, which individual PD case where i j, max = P + D, because the array index can not take negative, then we add a correction value to fix = 20 * m
But many online wording is problematic, so the correct solution should enumerate: the election of people -> selected as the first few people who -> value of PD, choose an enumeration of people, we start early enumeration minimum, so that the person can be selected such that lexicographic order, a method of recording on a path vector path [i] [j] corresponding to the selected record in the case where dp [i] [j] of the human
(In fact, this should be regarded as more conventional DP adds some routine questions, such as restrictions on the total number of records and path)
Code area
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include<queue> #include<string> #include<fstream> #include<vector> #include<stack> #include <map> #include <iomanip> #define bug cout << "**********" << endl #define show(x, y) cout<<"["<<x<<","<<y<<"] " #define LOCAL = 1; using namespace std; typedef long long ll; const ll inf = 1e18 + 7; const ll mod = 1e9 + 7; const int Max = 2e2 + 10; int n, m; int sub[Max], add[Max]; int dp[25][805]; vector<int> path[25][805]; int main() { #ifdef LOCAL // freopen("input.txt", "r", stdin); // freopen("output.txt", "w", stdout); #endif int kCase = 0; while (scanf("%d%d", &n, &m) != EOF && n + m) { for (int i = 1, p, d; i <= n; i++) scanf("%d%d", &p, &d), sub[i] = p - d, add[i] = p + d; int fix = 20 * m; for (int i = 0; i <= m; i++) for (int j = 0; j <= 2 * fix; j++) path[i][j].clear(), dp[i][j] = -1; dp[0][fix] = 0; for (int i = 1; i <= n; i++) for (int j = m - 1; j >= 0; j--) for (int k = 0; k <= 2 * fix; k++) if (dp[j][k] >= 0 && dp[j][k] + add[i] > dp[j + 1][k + sub[i]]) { dp[j + 1][k + sub[i]] = dp[j][k] + add[i]; path[j + 1][k + sub[i]] = path[j][k]; path[j + 1][k + sub[i]].push_back(i); } int dis; for (dis = 0; dis <= fix; dis++) { if (dp[m][fix - dis] >= 0 || dp[m][fix + dis] >= 0) break; } int S = dp[m][fix - dis] > dp[m][fix + dis] ? fix - dis : fix + dis; int P = (dp[m][S] + S - fix) / 2; int D = (dp[m][S] - S + fix) / 2; printf("Jury #%d\n", ++kCase); printf("Best jury has value %d for prosecution and value %d for defence:\n", P, D); for (int i = 0; i < m; i++) { printf("%d%c", path[m][S][i], i == path[m][S].size() - 1 ? '\n' : ' '); } printf("\n"); } return 0; }