• 【dp每日一题】POJ 1015 Jury Compromise


    大意:

    n个候选人,从中选出m个人。

    控方和辩方会根据对候选人的喜欢程度,给所有候选人打分,分值从0到20。选出的m个人,必须满足辩方总分和控方总分的差的绝对值最小。如果有多种选择方案的辩方总分和控方总分的之差的绝对值相同,那么选辩控双方总分之和最大的方案即可。

    思路:

    (dp[i][k])代表选了i个人且控辩差为k的情况下,控辩和的最大值。

    为了处理方便,需要将k都加上m*20,这样保证所有的k都是大于等于0的。

    初始将dp数组赋值为-1,(dp[0][m*20]=0),只有当dp数组不等于-1时可以通过这个状态转移,同时需要保证要选的人之前没有选过,那么只需要维护一个pre数组记录达到当前状态选了哪些人即可

    #include <iostream>
    #include <string.h>
    #include <stdio.h>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <algorithm>
    #include <math.h>
    #include <cstdio>
    using namespace std;
    
    const int N = 200 + 5;
    typedef long long LL;
    int n, m, a[N], b[N], dp[25][1000], maxk, pre[25][1000], res[25];
    int cases = 0;
    int main() {
        while (cin >> n >> m && (n + m != 0)) {
            cases++;
            memset(dp, -1, sizeof dp);
            memset(pre, -1, sizeof pre);
            for (int i = 0; i < n; i++) {
                cin >> a[i] >> b[i];
            }
            maxk = m * 20;
            dp[0][maxk] = 0;
            for (int i = 0; i < m; i++)
                for (int k = 0; k <= maxk * 2; k++)
                    if (dp[i][k] != -1)
                        for (int j = 0; j < n; j++) {
                            if (a[j] + b[j] + dp[i][k] >
                                dp[i + 1][k + a[j] - b[j]]) {
                                int x = i, y = k;
                                while (x > 0 && pre[x][y] != j) {
                                    y = y - (a[pre[x][y]] - b[pre[x][y]]);
                                    x--;
                                }
                                if (x == 0) {  // j不在路径内
                                    pre[i + 1][k + a[j] - b[j]] = j;
                                    dp[i + 1][k + a[j] - b[j]] =
                                        a[j] + b[j] + dp[i][k];
                                }
                            }
                        }
            int k = 0;
            for (k = 0; k <= maxk; k++) {
                if (dp[m][k + maxk] != -1) break;
                if (dp[m][-k + maxk] != -1) break;
            }
            if (dp[m][k + maxk] > dp[m][-k + maxk])
                k = k + maxk;
            else
                k = maxk - k;
            cout << "Jury #" << cases << endl;
            cout << "Best jury has value " << (k - maxk + dp[m][k]) / 2
                 << " for prosecution and value " << (dp[m][k] - k + maxk) / 2
                 << " for defence: " << endl;
            for (int i = m; i > 0; i--) {
                res[i-1] = pre[i][k]+1;
                k = k - (a[pre[i][k]] - b[pre[i][k]]);
            }
            sort(res, res + m);
            for (int i = 0; i < m; i++) cout << ' ' << res[i];
            cout << endl;
        }
        return 0;
    }
    
  • 相关阅读:
    【loj6179】Pyh的求和
    【bzoj4036】按位或
    【CF472G】Design Tutorial: Increase the Constraints
    【bzoj4811】由乃的OJ
    双马尾机器人(???)
    【codechef】Children Trips
    【bzoj3796】Mushroom追妹纸
    【bzoj4571】美味
    前夕
    【bzoj3589】动态树
  • 原文地址:https://www.cnblogs.com/dyhaohaoxuexi/p/14209530.html
Copyright © 2020-2023  润新知