“访问”美术馆

Posted captain1

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了“访问”美术馆相关的知识,希望对你有一定的参考价值。

传送门

这是一道神奇的树形DP,对它还是不需要建树,而且完全可以一边读入,一边DP出结果……

首先我们看题目描述很显然是一棵二叉树,而且还是完全二叉树。(没啥卵用)

令dp[i][j]表示在第i个节点选取花费j时间所能获取的最大画数。

之后因为题目的输入是递归给出的……所以我们直接去建图难度很大,不妨直接边递归边求解。首先我们考虑,如果当前的节点是一个不会再分裂的点(他下面直接通向展览馆)。我们直接更新这个节点的答案就可以。

之后如果他要能再分裂,先递归下去,之后在返回的途中,枚举对于左子树给其分配的偷窃时间,这样进行合并就可以啦。

注意因为这哥们偷完东西得跑出去,所以相当于每条道路的权值要<<1,还有就是他必须在警察来之前1秒必须跑出去,所以读入要--。

然后就可以做了。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
#include<set>
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define enter putchar(‘
‘)

using namespace std;
typedef long long ll;
const int M = 100005;

int read()
{
    int ans = 0,op = 1;
    char ch = getchar();
    while(ch < 0 || ch > 9)
    {
        if(ch == -) op = -1;
        ch = getchar();
    }
    while(ch >= 0 && ch <= 9)
    {
        ans *= 10;
        ans += ch - 0;
        ch = getchar();
    }
    return ans * op;
}


int cnt,tot,n,m,dp[105][605];

void dfs()
{
    int ro = ++cnt,lim;
    lim = read(),tot = read(),lim <<= 1;
    if(tot) rep(t,lim,n) dp[ro][t] = min((t-lim) / 5,tot);//已经到展览馆就更新
    else
    {
        int l = cnt+1;dfs();
        int r = cnt+1;dfs();
        rep(t,lim,n)
        rep(lt,0,t-lim)
        dp[ro][t] = max(dp[ro][t],dp[l][lt] + dp[r][t-lt-lim]);//更新答案
    }
}

int main()
{
    n = read(),n--;
    dfs();
    printf("%d
",dp[1][n]); 
    return 0;
}

 

以上是关于“访问”美术馆的主要内容,如果未能解决你的问题,请参考以下文章

P1270 “访问”美术馆(树形dp)

“访问”美术馆

luogu1270 “访问”美术馆 树形dp

P1270 “访问”美术馆

[luogu 1270] “访问”美术馆 (树形dp)

题解 P1270 “访问”美术馆