• Codeforces 1316E Team Building


    Description

    你需要组建一支排球队。为了组织一支排球队,你需要为队伍里的 $p$ 个不同的位置,从 $n$ 个人中选出 $p$ 个人,且每个位置上都恰好有一个人。另外还需要从剩下的人中选出恰好 $k$ 个人作为观众。

    对于第 $i$ 个人,已知他作为观众时能为队伍增加 $a_i$ 点力量,还有他在队伍的第 $j$ 个位置上时能为队伍增加 $s_{i,j}$ 点力量。

    请问这只排球队力量的最大值是多少?

    Solution

    看到 $p$ 很小,考虑状态压缩 DP。

    这里先把每个人按照 $a_i$ 降序排序。

    设想,对于一个状态 $f_{i, s}$,$s$ 是一个 $p$ 位二进制数,表示队伍的选择情况,当前这个 $i$ 会不会被选进观众呢?

    这里用到一个贪心,如果 $i le operatorname{CountBit}(s) + k$,那么,我们就会把 $i$ 选到观众里面去。

    这很好理解,原本应该是选前 $k$ 个当观众,但是有 $operatorname{CountBit}(s)$ 个已经被选到队伍里面去了,所以我们把限制往后移这么多位。

    接下来,考虑把 $i$ 弄成队员。我们枚举一个 $s$ 包含的位置 $t$,试图把 $i$ 放进去,那么就要用 $f_{i-1, s oplus 2^t}$ 来更新 $f_{i, s}$。

    这题作为状态压缩 DP 还是比较好实现的,时间复杂度 $mathcal O(n cdot 2^p)$,具体细节可以看代码。代码中用 $j$ 代替了 $s$。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int N = 1e5 + 5, P = 130;
    struct people
    {
        LL a, s[7];
        bool operator < (const people &oth) const { return a > oth.a; }
    } peo[N];
    int n, p, k;
    inline int CountBit(int x)
    {
        int res = 0;
        while(x) res++, x &= x - 1;
        return res;
    } 
    LL f[N][P];
    int main()
    {
        scanf("%d %d %d", &n, &p, &k);
        for(int i = 1; i <= n; i++) scanf("%lld", &peo[i].a);
        for(int i = 1; i <= n; i++)
            for(int j = 0; j < p; j++)
                scanf("%lld", &peo[i].s[j]);
        sort(peo + 1, peo + n + 1);
        int full = 1 << p;
        memset(f, -0x3f, sizeof f);
        f[0][0] = 0;
        for(int i = 1; i <= n; i++)
        {
            for(int j = 0; j < full; j++)
            {
                int cnt = CountBit(j);
                f[i][j] = f[i - 1][j];
                if(i <= cnt + k) f[i][j] = max(f[i][j], f[i - 1][j] + peo[i].a);
                for(int t = 0; t < p; t++) if(j >> t & 1)
                    f[i][j] = max(f[i][j], f[i - 1][j ^ (1 << t)] + peo[i].s[t]);
            }
        }
        printf("%lld
    ", f[n][full - 1]);
        return 0;
    }
  • 相关阅读:
    JAVA 数据结构(16):SET(一)Java HashSet
    JAVA 数据结构(15):LIST(二)Java LinkedList
    PGSQL数据库里物化视图【materialized view】
    PGSQL存储过程学习
    PostgreSQL数据库结构
    javascript里面的document.getElementById
    odoo14学习----x2many操作与图片设置继承image.mixin
    odoo14在tree、kanban视图上添加dashboard
    odoo14在列表视图里添加自定义按钮
    python开发包之pyecharts
  • 原文地址:https://www.cnblogs.com/syksykCCC/p/CF1316E.html
Copyright © 2020-2023  润新知