[CERC2014] Outer space invaders

[CERC2014] Outer space invaders

区间 \(DP\) , 按照时间设计状态, 但是由于时间的数据范围比较大, 而数据的个数很少, 我们只关心时间的相对大小而不关心具体时间, 那我们就可以离散化. 这样就可以把时间的范围从 \(1e4\) 缩到 \(600\) . 复杂度 \(O(n^3)\) , 完全可以过.

\(f[i][j]\) 表示把时间 \([i, j]\) 完全包含, 也就是 \(a \ge i, b \le j\) 的所有外星人消灭的最小花费, 然后我们贪心.

如果在时间 \(j\) 要消灭第 \(i\) 个外星人, 那么所有满足 \(a \ge j, b \le j, d \le d[i]\) 的外星人都会被消灭, 所以我们枚举区间长度 \(l\) , 枚举左端点 \(i\) , 再找出包含于 \([i, j]\)\(d\) 最大的外星人 \(id\) , 然后枚举 \(k \in [a[id], b[id]]\) , 转移 \(f[i][j] = \min(f[i][j], f[i][k - 1] + f[k + 1][j] + d[id])\) .

因为我们是求的被区间 \([i, j]\) 完全包含的全部消灭的最小花费, 所以我们不用担心转移的时候会有没有被消灭的以及重复消灭的.

\(code:\)

#include <bits/stdc++.h>
using namespace std;
int read() {
    int x = 0, f = 1;
    char ch = getchar();
    while (!isdigit(ch)) {
        if (ch == '-') f = -1;
        ch = getchar();
    }
    while (isdigit(ch)) {
        x = (x << 1) + (x << 3) + (ch ^ 48);
        ch = getchar();
    }
    return x * f;
}
const int N = 605, inf = 1 << 30;
int n, f[N][N], mp[10005];
struct alien {
    int a, b, d;
} s[N];
bool cmp(alien x, alien y) {
    return x.b < y.b;
}
int init() {
    memset(f, 0, sizeof(f));
    memset(mp, 0, sizeof(mp));
    n = read(); int cnt = 0, tot = 0;
    for (int i = 1; i <= n; i++) {
        s[i].a = read(), s[i].b = read(), s[i].d = read();
        tot = max(tot, max(s[i].a, s[i].b));
        mp[s[i].a] = mp[s[i].b] = 1;
    }
    for (int i = 1; i <= tot; i++) if (mp[i]) mp[i] = ++cnt;
    sort(s + 1, s + n + 1, cmp);
    for (int i = 1; i <= n; i++) s[i].a = mp[s[i].a], s[i].b = mp[s[i].b];
    return cnt;
}
void solve(int m) {
    for (int l = 1; l <= m; l++) {
        for (int i = 1; i + l - 1 <= m; i++) {
            int j = i + l - 1, id = 0;
            for (int k = 1; k <= n; k++) if (s[k].a >= i && s[k].b <= j && (!id || s[id].d < s[k].d)) id = k;
            if (!id) continue; f[i][j] = inf;
            for (int k = s[id].a; k <= s[id].b; k++) f[i][j] = min(f[i][j], f[i][k - 1] + f[k + 1][j] + s[id].d);
        }
    }
    printf("%d\n", f[1][m]);
}
int main() {
    int T = read();
    while (T--) {
        solve(init());
    }
    return 0;
}
posted @ 2021-08-23 18:31  sshadows  阅读(37)  评论(0编辑  收藏  举报