1 条题解

  • 0
    @ 2026-10-26 19:23:52

    思路与算法

    设S[j]为累计伤害。若上次施法在t,此后j时刻伤害结算后的生命为hp-S[j]+15t。固定冷却CD,DP枚举可达施法时刻t,再枚举生命仍为正的后续时刻j,满足间隔则可施法;t=0表示尚未施法,不限制第一次。若能活过n则CD可行,利用单调性二分最大CD;CD=n可行表示至多一次施法,输出无穷。

    正确性说明

    所有积蓄的治疗在施法时一并释放,至t累计治疗恰为15t,与此前施法划分无关,所以只记录最后时刻足够。扫描遇生命≤0便不能再挽救,DP恰好枚举所有合法施法序列。增大CD只删合法序列,二分正确。

    复杂度

    每次判定O(n²),二分O(logn),读入生命字符串长L,总O(L+n²logn)时间,O(n)空间;前缀和与DP初始化计入。

    易错点

    先受伤后治疗,生命0已经死亡。初始生命可极长,正伤总量≤500000,截为500001保持生存判断。最小CD也不可行输出-1,无穷需单独判断。

    参考代码(C++11)

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int n;
        string h;
        cin >> n >> h;
        int hp = 0;
        for (char c : h)
            hp = min(500001, hp * 10 + c - '0');
        vector<int> s(n + 1);
        for (int i = 1, x; i <= n; i++) {
            cin >> x;
            s[i] = s[i - 1] + x;
        }
        auto feasible = [&](int cd) {
            vector<int> can(n + 1);
            can[0] = 1;
            for (int t = 0; t <= n; t++)
                if (can[t]) {
                    bool alive = true;
                    for (int j = t + 1; j <= n; j++) {
                        if (hp - s[j] + 15 * t <= 0) {
                            alive = false;
                            break;
                        }
                        if (t == 0 || j - t >= cd)
                            can[j] = 1;
                    }
                    if (alive)
                        return true;
                }
            return false;
        };
        if (feasible(n)) {
            cout << "No upper bound.\n";
            return 0;
        }
        if (!feasible(1)) {
            cout << -1 << '\n';
            return 0;
        }
        int l = 1, r = n - 1;
        while (l < r) {
            int m = (l + r + 1) / 2;
            if (feasible(m))
                l = m;
            else
                r = m - 1;
        }
        cout << l << '\n';
    }
    
    • 1

    信息

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