CODEVS1163访问艺术馆(第一道大师水题)

题目描述 Description

皮尔是一个出了名的盗画者,他经过数月的精心准备,打算到艺术馆盗画。艺术馆的结构,每条走廊要么分叉为二条走廊,要么通向一个展览室。皮尔知道每个展室里藏画的数量,并且他精确地测量了通过每条走廊的时间,由于经验老道,他拿下一副画需要5秒的时间。你的任务是设计一个程序,计算在警察赶来之前(警察到达时皮尔回到了入口也算),他最多能偷到多少幅画。

输入描述 Input Description

第1行是警察赶到得时间,以s为单位。第2行描述了艺术馆得结构,是一串非负整数,成对地出现:每一对得第一个数是走过一条走廊得时间,第2个数是它末端得藏画数量;如果第2个数是0,那么说明这条走廊分叉为两条另外得走廊。数据按照深度优先得次序给出,请看样例

输出描述 Output Description

输出偷到得画得数量

样例输入 Sample Input

60

7 0 8 0 3 1 14 2 10 0 12 4 6 2

样例输出 Sample Output

2

思路:首先读懂题意,不一定要取完一个画室中的画,取一幅画要5s,没看到这两件事,让我蛋疼的写了个简单的深搜,结果。。。错了。。。
先用递归建树,保存一下父节点,儿子节点,到父亲的距离,自己末端的画数(有的变量可能用不到)。然后开始树状dp,f[i][j]表示第i个节点取j幅画,然后对左右子树进行选择。一点点的算出来。
注意每次循环就是从0-该子树最多的画数(用一个数组保存一下),还有一点,work时,从0开始递归,因为input时把1的父节点默认为了0。。。(这个肮脏的错误让我很。。。)

code:

#include<cstdio>

#include<iostream>

#include<cstring>

using namespace std;

struct use{

int fa,d,va,l,r;

}a[1000];

int s,n=0,su[500]={0},ans=0;

long long f[500][10000]={0};

void input(int faa)

{

int x,y,t;

cin>>x>>y;

++n;t=n;

if (a[faa].l==0) a[faa].l=n;

else a[faa].r=n;

a[n].fa=faa;

a[n].d=x*2;

if (y==0)

{

input(t);

input(t);

}

else

a[t].va=y;

}

void work(int i)

{

int j,k,l1,l2;

if (a[i].l==0)

{

su[i]=a[i].va;

for (j=1;j<=a[i].va;++j)

f[i][j]=5*j;

return;

}

work(a[i].l);

if (i!=0)

work(a[i].r);

f[i][0]=0;

for (k=1;k<=su[a[i].r];++k)

f[i][k]=min(f[i][k],f[a[i].r][k]+a[a[i].r].d);

for (j=1;j<=su[a[i].l];++j)

f[i][j]=min(f[i][j],f[a[i].l][j]+a[a[i].l].d);

for (j=1;j<=su[a[i].l];++j)

for (k=1;k<=su[a[i].r];++k)

f[i][j+k]=min(f[i][j+k],f[a[i].l][j]+a[a[i].l].d+a[a[i].r].d+f[a[i].r][k]);

su[i]=su[a[i].l]+su[a[i].r];

}

int main()

{

int i,j;

cin>>s;

memset(a,0,sizeof(a));

memset(f,127,sizeof(f));

input(0);

work(0);

for (i=1;i<=su[0];++i)

if (f[0][i]<=s&&i>ans) ans=i;

cout<<ans<<endl;

}

时间: 2024-10-14 15:34:11

CODEVS1163访问艺术馆(第一道大师水题)的相关文章

codevs1163访问艺术馆(树形dp)

1163 访问艺术馆 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 皮尔是一个出了名的盗画者,他经过数月的精心准备,打算到艺术馆盗画.艺术馆的结构,每条走廊要么分叉为二条走廊,要么通向一个展览室.皮尔知道每个展室里藏画的数量,并且他精确地测量了通过每条走廊的时间,由于经验老道,他拿下一副画需要5秒的时间.你的任务是设计一个程序,计算在警察赶来之前(警察到达时皮尔回到了入口也算),他最多能偷到多少幅画. 输入描述 Input

codevs1163 访问艺术馆

题目描述 Description 皮尔是一个出了名的盗画者,他经过数月的精心准备,打算到艺术馆盗画.艺术馆的结构,每条走廊要么分叉为二条走廊,要么通向一个展览室.皮尔知道每个展室里藏画的数量,并且他精确地测量了通过每条走廊的时间,由于经验老道,他拿下一副画需要5秒的时间.你的任务是设计一个程序,计算在警察赶来之前(警察到达时皮尔回到了入口也算),他最多能偷到多少幅画. 输入描述 Input Description 第1行是警察赶到得时间,以s为单位.第2行描述了艺术馆得结构,是一串非负整数,成对

某5道CF水题

1.PolandBall and Hypothesis 题面在这里! 大意就是让你找一个m使得n*m+1是一个合数. 首先对于1和2可以特判,是1输出3,是2输出4. 然后对于其他所有的n,我们都可以非常快的找到一个最小的与它互质的质数p(考虑反证法),并且满足p<n. 这样就相当与解一个同余方程 n*m = p-1 (mod p) , 解出的m可以保证 n*m+1 是 p 的倍数,也就是合数了. 又因为gcd(p,n)==1,所以这个方程肯定有解,直接求一个 n 在mod p意义下的逆元然后乘

几道cf水题

题意:给你包含n个元素的数组和k种元素,要求k种元素要用完,并且每种颜色至少用一次,n个元素,如果某几个元素的值相同,这些个元素也不能染成同一种元素. 思路:如果元素个数n小于k或者值相同的元素的个数大于k,那么一定无解,输出-1.用一个num[a[i]]记录每种相同值的元素出现次数,若大于k,无解.这道题的关键在于如何处理值相同的这些元素,可以用一个二维数组f[i][j]来表示状态,其中i表示对应元素值,j代表颜色.只要对于相同的i,j值不同就可以了.每个元素用什么颜色记录在一个数组ans[i

hdu 1520 Anniversary party(第一道树形dp)

传送门: http://acm.hdu.edu.cn/showproblem.php?pid=1520 Anniversary party Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 16376    Accepted Submission(s): 6241 Problem Description There is going to

POJ百道水题列表

以下是poj百道水题,新手可以考虑从这里刷起 搜索1002 Fire Net1004 Anagrams by Stack1005 Jugs1008 Gnome Tetravex1091 Knight Moves1101 Gamblers1204 Additive equations 1221 Risk1230 Legendary Pokemon1249 Pushing Boxes 1364 Machine Schedule1368 BOAT1406 Jungle Roads1411 Annive

刷了500道水题是什么体验?

并没有什么卵用. 我马上大二了,大一两学期目测切了1000道水题了,毫无意义. 至今不理解kmp和后缀数组,只会模板.数论和博弈论是什么?能吃吗?只会打表.图论至今不会tarjan,话说dlx是什么?插头dp,这是什么?数据结构还好,经常做高中生的题,可持久化可持久化线段树也能花一下午时间写出来,然而并不会考. 平时做题只刷水题,遇到难题的时候,随手搜题解,看了看,哇,这居然能这么搞!然后抄一遍别人代码,交上去ac. cf一年几乎没缺过,花了大一上半年时间才滚上div1.然而至今紫号一堆,黄名一

大数--几道水题,用来学学JAVA

几道水题,练习一下JAVA写大数 poj2305  Basic remains 大数可以直接用非十进制读入,读入的数在变量中是十进制的 输出的时候要先用BigInteger的toString方法转换为相应的进制 1 import java.math.*; 2 import java.util.*; 3 class Main 4 { 5 public static void main(String[] args) 6 { 7 Scanner cin = new Scanner(System.in)

hdu 4405 概率dp 2012年金华亚洲网络赛--虽然水,但是是自己独立做的第一道概率dp

题目:http://acm.hdu.edu.cn/showproblem.php?pid=4405 e[i]:当前在位置i还需要走的步数期望 受刘汝佳的AC自动机那个后缀链接写法的启发,我的x[i]通过逆序算出来连续有"flight line "的时候,能到达的最远距离, rep(i,0,m) { scanf("%d%d",&xx,&yy); x[xx]=yy; } for(int i=n;i>=0;i--) if(x[i]!=-1 &