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

题意

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

分析

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

x结点考虑分给左右结点的时间,故枚举分给左儿子的时间i,那么分给右儿子的时间就是ticost[x]

dp[x][t]=max(dp[x][t],dp[x<<1][i]+dp[x<<1|1][ticost[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 @   SxtoxA  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
12 13
点击右上角即可分享
微信分享提示