访问艺术馆 codevs1163 树形dp

来源:互联网 发布:钱学森被美国监禁 知乎 编辑:程序博客网 时间:2024/04/30 09:21

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 1001int f[N][S], l[N], r[N], p[N][N], 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;}
1 0
原创粉丝点击