您的位置:首页 > 其它

访问艺术馆 codevs1163 树形dp

2017-03-22 17:43 232 查看

Description

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

Solution

题目很裸了已经o(︶︿︶)o

显然给出的是一颗二叉树,那么考虑树形dp。设f[i][j]为i节点j时间偷多少幅画,那么转移有三种,分别从左子树走,右子树走,两边一起走。两边走的情况枚举一下分配时间就行了

Code

#include <stdio.h>
#define rep(i, st, ed) for (int i = st; i <= ed; i += 1)
#define N 4001
#define S 1001
int f
[S], l
, r
, p

, cnt;
inline void add(int now, int cnt, int w){
if (!l[now]){
l[now] = cnt;
}else if (!r[now]){
r[now] = cnt;
}
p[now][cnt] = w;
}
int s;
inline void init(int t){
rep(i, 1, t){
rep(j, i * 5, i * 5 + 4){
f[cnt][j] = i;
}
}
}
inline void dfs1(int now){
int w, t;
scanf("%d%d", &w, &t);
cnt += 1;
add(now, cnt, w * 2);
if (t){
init(t);
}else{
dfs1(cnt);
}
scanf("%d%d", &w, &t);
cnt += 1;
add(now, cnt, w * 2);
if (t){
init(t);
}else{
dfs1(cnt);
}
}
inline int max(int x, int y){
return x>y?x:y;
}
inline void dfs2(int now){
if (l[now]){
dfs2(l[now]);
}
if (r[now]){
dfs2(r[now]);
}
if (!l[now] && !r[now]){
return;
}
rep(j, 1, s){
f[now][j] = max(f[now][j], f[l[now]][j - p[now][l[now]]]);
f[now][j] = max(f[now][j], f[r[now]][j - p[now][r[now]]]);
rep(kl, 1, j - 1){
int kr = j - kl;
f[now][j] = max(f[now][j], f[l[now]][kl - p[now][l[now]]] + f[r[now]][kr - p[now][r[now]]]);
}
}
}
int main(void){
scanf("%d", &s);
int n = 0;
cnt = 2;
int w, t;
scanf("%d%d", &w, &t);
l[1] = 2;
p[1][2] = w * 2;
dfs1(2);
dfs2(1);
printf("%d\n", f[1][s]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: