洛谷P1270 “访问”美术馆 树形dp

题意

https://www.luogu.com.cn/problem/P1270

分析

经典的树上背包,令\(dp[x][t]\)表示在\(x\)点剩余\(t\)秒的最多画数

\(x\)结点考虑分给左右结点的时间,故枚举分给左儿子的时间\(i\),那么分给右儿子的时间就是\(t-i-cost[x]\)

\[dp[x][t]=max(dp[x][t],dp[x<<1][i]+dp[x<<1|1][t-i-cost[x]]) \]

答案即是\(dp[1][T]\)

Code

#include<iostream>
#include<cstdio>
#include<vector>

const int maxn = 200 + 10;
int T;
int cost[maxn], val[maxn];
int dp[maxn][2000 + 10];

void read(int x) {
    int a, b;
    scanf("%d%d", &a, &b);
    cost[x] = 2 * a;
    val[x] = b;
    if (val[x]) return;
    read(x << 1);
    read(x << 1 | 1);
}

void dfs(int x) {
    if (val[x]) {
        for (int i = 0; i <= val[x]; i++) {
            if (i * 5 + cost[x] > T)break;
            dp[x][i * 5 + cost[x]] = i;
        }
        return;
    }
    dfs(x << 1);
    dfs(x << 1 | 1);
    for (int i = cost[x]; i <= T; i++)
        for (int j = 0; j <= i - cost[x]; j++)
            dp[x][i] = std::max(dp[x][i], dp[x << 1][j] + dp[x << 1 | 1][i - j - cost[x]]);
}

int main() {
    scanf("%d", &T);
    T--;
    read(1);
    dfs(1);
    printf("%d", dp[1][T]);
    return 0;
}
posted @ 2022-11-20 15:29  SxtoxA  阅读(23)  评论(0)    收藏  举报
12 13