Codeforces 815C Karen and Supermarket 树形dp

Karen and Supermarket

感觉就是很普通的树形dp。

dp[ i ][ 0 ][ u ]表示在 i 这棵子树中选择 u 个且 i 不用优惠券的最小花费。

dp[ i ][ 1 ][ u ]表示在 i 这棵子树中选择 u 个且 i 用优惠券的最小花费。

注意这个转移总的合起来是O(n ^ 2)的。

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define PLL pair<LL, LL>
#define PLI pair<LL, int>
#define PII pair<int, int>
#define SZ(x) ((int)x.size())
#define ull unsigned long long
using namespace std;

const int N = 5000 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-8;

int n, b, d[N], c[N], fa[N];
vector<int> G[N];

int dp[N][2][N];
int tmp[N][2][N];
int sum[N];

void dfs(int u) {
    sum[u] = 1;
    memset(dp[u], inf, sizeof(dp[u]));
    dp[u][0][0] = 0;
    dp[u][0][1] = c[u];
    dp[u][1][1] = c[u] - d[u];
    for(auto& v : G[u]) {
        dfs(v);
        memset(tmp[u], INF, sizeof(tmp[u]));
        for(int i = 0; i <= sum[u]; i++) {
            for(int j = 0; j <= sum[v]; j++) {
                tmp[u][0][i + j] = min(tmp[u][0][i + j], dp[u][0][i] + dp[v][0][j]);
                tmp[u][1][i + j] = min(tmp[u][1][i + j], dp[u][1][i] + dp[v][0][j]);
                tmp[u][1][i + j] = min(tmp[u][1][i + j], dp[u][1][i] + dp[v][1][j]);
            }
        }
        sum[u] += sum[v];
        memcpy(dp[u], tmp[u], sizeof(dp[u]));
    }
}

int main() {
    scanf("%d%d", &n, &b);
    for(int i = 1; i <= n; i++) {
        scanf("%d%d", &c[i], &d[i]);
        if(i > 1) {
            scanf("%d", &fa[i]);
            G[fa[i]].push_back(i);
        }
    }
    dfs(1);
    for(int i = n; i >= 0; i--) {
        if(dp[1][0][i]  <= b || dp[1][1][i] <= b) {
            printf("%d\n", i);
            return 0;
        }
    }
    return 0;
}

/*
*/

猜你喜欢

转载自www.cnblogs.com/CJLHY/p/10450592.html