1 条题解

  • 0
    @ 2026-10-26 14:35:24

    思路与算法

    令1表示动物保留。预计算每个起点E和其5位窗口的快乐人数:至少一个喜欢位为1或害怕位为0就快乐。枚举最初4个围栏状态,在长度4的滑动掩码上DP,每步追加下一位并计当前窗口收益。最后4步追加位必须等于最初4位,闭合圆环后取最大值。

    正确性说明

    每个游客的条件完全取决于其5个连续围栏,预处理准确反映题目两个条件的析取。给定前4位后,每个后续位选择恰对应一种完整移除方案,DP记录同一4位边界下的最大已结算收益,历史其他位不再影响未来。末尾强制回到起始4位,确保跨尾首窗口也按同一个圆环计分,枚举16个起始状态覆盖全部方案。

    复杂度

    预处理O(32C),DP为O(16×N×16×2),即O(C+N)但常数需保留。空间O(32N+16),初始化所有窗口计数O(32N),已包含。N≤10000、C≤50000,计数int足够。

    易错点

    害怕动物被移走就快乐,不是所有害怕动物都要移走。喜欢与害怕按题目OR判断。E接近N时围栏号需取模,最后4步不能自由选。独立小规模枚举全部2^N保留方案;最大规模用每点3喜欢/2害怕的独立投票及全喜欢构造核验。

    参考代码(C++11)

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int n, c;
        cin >> n >> c;
        vector<array<int, 32>> reward(n);
        for (int i = 0; i < c; ++i) {
            int e, F, L;
            cin >> e >> F >> L;
            --e;
            int fear = 0, like = 0;
            for (int j = 0, x; j < F; ++j) {
                cin >> x;
                fear |= 1 << ((x - 1 - e + n) % n);
            }
            for (int j = 0, x; j < L; ++j) {
                cin >> x;
                like |= 1 << ((x - 1 - e + n) % n);
            }
            for (int mask = 0; mask < 32; ++mask)
                reward[e][mask] += bool((mask & like) || ((~mask) & fear));
        }
        int answer = 0, NEG = -1000000000;
        for (int initial = 0; initial < 16; ++initial) {
            array<int, 16> dp;
            dp.fill(NEG);
            dp[initial] = 0;
            for (int e = 0; e < n; ++e) {
                array<int, 16> next;
                next.fill(NEG);
                for (int state = 0; state < 16; ++state)
                    if (dp[state] > NEG)
                        for (int b = 0; b < 2; ++b) {
                            if (e + 4 >= n && b != ((initial >> (e + 4 - n)) & 1))
                                continue;
                            int mask = state | (b << 4), ns = (state >> 1) | (b << 3);
                            next[ns] = max(next[ns], dp[state] + reward[e][mask]);
                        }
                dp = next;
            }
            answer = max(answer, dp[initial]);
        }
        cout << answer << '\n';
    }
    
    • 1

    信息

    ID
    1775
    时间
    1000ms
    内存
    512MiB
    难度
    普及+
    标签
    递交数
    1
    已通过
    1
    上传者