UVA323 Jury Compromise

UVA323 Jury Compromise - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

由于选择人数有限制(等于 \(m\)),因此考虑将人数设入动态规划的一维。

考虑目标是 \(D + P\) 最大,那么考虑背包,将 \(D + P\) 考虑成物品的总价值。

\(f(i, j, k)\),表示前 \(i\) 个人中选了 \(j\) 个人,\(D - P = k\)\(D + P\) 的最大值。

转移:\(f(i, j, k) = \max(f(i - 1, j, k), f(i - 1, j - 1, k - d[i] + p[i]) + d[i] + p[i])\)

采用类似思想滚动第一维,由于是个 01 背包,可以彻底滚动掉。访问 \(f(j - 1, k - d[i] + p[i])\) 必须还处在 \(i - 1\) 这个阶段,所以 \(j\) 应倒序枚举。

不过,记录路径的数组不可以压缩维度!

/*
 * @Author: crab-in-the-northeast 
 * @Date: 2022-11-12 04:14:51 
 * @Last Modified by: crab-in-the-northeast
 * @Last Modified time: 2022-11-12 05:24:51
 */
#include <bits/stdc++.h>
inline int read() {
    int x = 0;
    bool f = true;
    char ch = getchar();
    for (; !isdigit(ch); ch = getchar())
        if (ch == '-')
            f = false;
    for (; isdigit(ch); ch = getchar())
        x = (x << 1) + (x << 3) + ch - '0';
    return f ? x : (~(x - 1));
}
inline bool gmx(int &a, int b) {
    return b > a ? a = b, true : false;
}

const int maxn = 205;
const int maxm = 25;
const int maxv = (maxm * 20) << 1;
const int par = maxm * 20;

int f[maxm][maxv];
int d[maxn], p[maxn];
int pre[maxn][maxm][maxv];

void pr(int i, int j, int k) {
    if (j == 0)
        return ;
    int id = pre[i][j][k + par];
    pr(id - 1, j - 1, k - d[id] + p[id]);
    printf(" %d", id);
}

int main() {
    for (int cas = 1, n = read(), m = read(); n; ++cas, n = read(), m = read()) {
        std :: memset(f, 0xc0, sizeof(f));
        f[0][par] = 0;
        for (int i = 1; i <= n; ++i) {
            p[i] = read();
            d[i] = read();
        }

        for (int i = 1; i <= n; ++i) {
            for (int j = m; j; --j)
                for (int k = -400; k <= 400; ++k)
                    if (gmx(f[j][k + par], 
                            f[j - 1][k - d[i] + p[i] + par] 
                            + d[i] + p[i]))
                        pre[i][j][k + par] = i;
                    else
                        pre[i][j][k + par] = pre[i - 1][j][k + par];
        }
        
        for (int dif = 0; dif <= 400; ++dif) {
            int ps = f[m][par + dif], ng = f[m][par - dif];
            if (ps < 0 && ng < 0)
                continue;
            int k = dif;
            if (ps < 0 || ng > ps)
                k = -dif;
            
            printf("Jury #%d\n", cas);
            printf("Best jury has value %d for prosecution and value %d for defence:\n", (f[m][k + par] - k) >> 1, (f[m][k + par] + k) >> 1);
            pr(n, m, k);
            puts("");
            puts("");
            break;
        }
    }

    return 0;
}
posted @ 2022-11-12 05:27  dbxxx  阅读(27)  评论(0编辑  收藏  举报