POJ 1015 Jury Compromise (knapsack problem recording path)

(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;
}
View Code

Guess you like

Origin www.cnblogs.com/winter-bamboo/p/11574402.html