洛谷P4322 [JSOI2016]最佳團體 題解 01分數規劃+樹上揹包

題目鏈接:https://www.luogu.com.cn/problem/P4322

解題思路:

01分數規劃 + 樹上揹包。

下面的代碼是 \(O(n^3)\) 的解法(不開O2會TLE一組數組):

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2505;
int K, n, a[maxn], b[maxn], p[maxn], sz[maxn];
double f[maxn][maxn], v[maxn];
vector<int> g[maxn];
void dfs(int u) {
    sz[u] = 1;
    f[u][0] = 0;
    f[u][1] = v[u];
    for (int i = 2; i <= K+1; i ++) f[u][i] = -1e9;
    for (auto v: g[u]) {
        dfs(v);
        sz[u] += sz[v];
        for (int j = min(K+1, sz[u]); j >= 1; j --)
            for (int k = 1; k <= min(sz[v], j-1); k ++)
                f[u][j] = max(f[u][j], f[u][j-k] + f[v][k]);
    }
}
bool check(double mid) {
    for (int i = 1; i <= n; i ++) v[i] = a[i] - mid * b[i];
    dfs(0);
    return f[0][K+1] >= 0;
}
int main() {
    cin >> K >> n;
    for (int i = 1; i <= n; i ++) {
        cin >> b[i] >> a[i] >> p[i];
        g[ p[i] ].push_back(i);
    }
    double L = 0, R = 10000.0;
    while (R - L > 1e-4) {
        double mid = (L + R) / 2;
        if (check(mid)) L = mid;
        else R = mid;
    }
    printf("%.3lf\n", L);
    return 0;
}

樹上揹包有 \(O(n^2)\) 的解法,抽時間學會了補上。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章