“访问”美术馆

传送门

这是一道神奇的树形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(‘\n‘)

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\n",dp[1][n]);
    return 0;
}

原文地址:https://www.cnblogs.com/captain1/p/9637176.html

时间: 2024-07-30 22:30:26

“访问”美术馆的相关文章

洛谷 P1270 “访问”美术馆(树形DP)

P1270 “访问”美术馆 题目描述 经过数月的精心准备,Peer Brelstet,一个出了名的盗画者,准备开始他的下一个行动.艺术馆的结构,每条走廊要么分叉为两条走廊,要么通向一个展览室.Peer知道每个展室里藏画的数量,并且他精确测量了通过每条走廊的时间.由于经验老到,他拿下一幅画需要5秒的时间.你的任务是编一个程序,计算在警察赶来之前,他最多能偷到多少幅画. 输入输出格式 输入格式: 第1行是警察赶到的时间,以s为单位.第2行描述了艺术馆的结构,是一串非负整数,成对地出现:每一对的第一个

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

P1270 “访问”美术馆 艺术馆最多有100个展室 ------> 节点数$<=100*2<2^{8}=256$ 所以可以开一个$f[i][j]$表示到第$i$个点为止花去$j$分钟的最大价值 对于分叉的点,我们可以直走右边或直走左边,也可以两边都走一次,分别转移即可. 对于展室(叶节点),处理一下几分钟能拿几幅画. 因为要折返所以边权$*2$,并且总时间花费要严格小于deadline,所以总时间-1 #include<iostream> #include<cstdi

luogu P1270 &quot;访问&quot;美术馆 树dp

传送门 比较奇怪的树形背包 首先需要处理读入的问题 这题史诗递归读入 然后递归读入就不用建图 这题特点是只有叶子有价值 所以背包就不太有用 坑点就是这个人进去还得出来... 而且不能把时间都用完(导致75) Time cost: 35min Code: 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 #include<queue> 6

luogu1270 “访问”美术馆 树形dp

传送门 树形dp f[i][j] - 到i号点,已经j时间了的最大偷画数 #include <bits/stdc++.h> using namespace std; typedef long long ll; #define rep(i, a, b) for(int i = a; i <= b; ++i) const int N = 107; const int S = 607; int s, n, f[N][S]; void dfs(int u) { int time, paint;

P1270 “访问”美术馆

一道树形dp啦~~~ 其实我是做过这道题的加强版后才做的这道题--不过先由浅入深,先发这个~ 首先,我定义 f [ u ] [ i ] 为在第 u 个点上,给它时间为 i 是能获取的最大价值. 有一个需要注意,如果说这是一个展厅,设给这个点的时间为 t ,那么实际能偷画的时间只有 t - 双倍边权. 这也导致了如果这个点是一个分支,那么我给两边的时间和(就是我给这个点的时间)必定要大于等于二倍边权. 这样就避免了在dfs里传入无关的冗杂的变量,使得状态统一比较容易维护. 接下来贴代码: #inc

做题单

错误 收藏了过多题目 QWQ P1383 高级打字机 P1270 “访问”美术馆 P1481 魔族密码 P1280 尼克的任务 P1271 聚会的快乐 P3631 [APIO2011]方格染色 P1243 排序集合 P2858 [USACO06FEB]奶牛零食Treats for the Cows P3146 [USACO16OPEN]248 P2890 [USACO07OPEN]便宜的回文Cheapest Palindrome P1896 [SCOI2005]互不侵犯 P3154 [CQOI2

[DP总结]树形DP

树形DP 树形DP,顾名思义,是在树上进行DP操作,因此往往需要使用DP实现,在转移时,通常先递归求出子树中的解,再在根节点进行计算转移. 树中只有两种关系,一种是父子关系,一种是平行关系. 下面是几道简单的树形DP.从中我们可以窥出树形DP的本质. [luogu] P1352 没有上司的舞会 题目描述 某大学有N个职员,编号为1~N.他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司.现在有个周年庆宴会,宴会每邀请来一个职员都会增加一定的快乐指数Ri,但是

初学树型dp

树型DP DFS的回溯是树形DP的重点以及核心,当回溯结束后,root的子树已经被遍历完并处理完了.这便是树形DP的最重要的特点 自己认为应该注意的点 好多人都说在更新当前节点时,它的儿子结点都给更新完了,实际上这并不准确.对于当前节点,我们需要dfs它的儿子,并且在dfs中进行dp.在此过程中并不是等到儿子都更新完我们才更新当前节点的信息(假设当前节点为x, 有儿子son1 , son2, son3, 且son1已经更新完了, 即x已有了son1的信息, son2刚刚更新完,即dfs正在son

Sqlserver通过链接服务器访问Oracle的解决办法

转自http://blog.sina.com.cn/s/blog_614b6f210100t80r.html 一.创建sqlserver链接服务(sqlserver链接oracle)  首先sqlserver 链接oracle可以通过两个访问接口: “MSDAORA” 和“OraOLEDB.Oracle” 1.“MSDAORA”访问接口是由Microsoft OLE DB Provider for Oracle提供的,这里建议不使用此接口进行链接.通过该访问接口建立的链接服务器在进行查询orac