偷天换日——树状DP

题目

猫和老鼠
神偷对艺术馆内的名画垂涎欲滴准备大捞一把。

艺术馆由若干个展览厅和若干条走廊组成。每一条走廊的尽头不是通向一个展览厅,就

是分为两个走廊。每个展览厅内都有若干幅画,每副画都有一个价值。经过走廊和偷画都是

要耗费时间的。

警察会在n 秒后到达进口,在不被逮捕的情况下你最多能得到的价值。

输入格式

第一行一个整数 n(n≤600)。

第二行若干组整数,对于每组整数(t,x),t 表示进入这个展览厅或经过走廊要耗费 t

秒的时间,若x>0 表示走廊通向的展览厅内有x 幅画,接下来

x对整数(w,c)表示偷一幅价值为 w 的画需要 c秒的时间。若

x=0 表示走廊一分为二。(t,c≤5; x≤30)

输入是按深度优先给出的。房间和走廊数不超过 300 个。

输出格式

仅一个整数,表示能获得的最大价值。

输入输出样例

样例输入

50 
5 0 10 1 10 1 5 0 10 2 500 1 1000 2 18 1 1000000 4 

样例输出

1500

题解

解题思路

没啥好说的,就是一树状DP,和选课类似
这个树没必要存

代码

#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 1e3+5;
int n, tot = 1, f[N][N], w[N], m[N];
void dfs(int x) {
    int a, b;
    scanf("%d%d", &a, &b);
    a <<= 1;
    if (b) {
        for(int i = 1; i <= b; i++)
            scanf("%d%d", &w[i], &m[i]);
        for(int i = 1; i <= b; i++)
            for(int j = n; j >= m[i] + a; j--)
                f[x][j] = max(f[x][j], f[x][j-m[i]] + w[i]);
    }
    else {
        int l = ++tot; dfs(l);
        int r = ++tot; dfs(r);
        for(int i = a; i <= n; i++)
            for(int j = 0; j <= i - a; j++)
                f[x][i] = max(f[x][i], f[l][j] + f[r][i-j-a]);
    }
}
int main() {
    scanf("%d", &n); n--;
    dfs(1); 
    printf("%d", f[1][n]);
    return 0;
}
posted @ 2020-04-24 20:09  Shawk  阅读(106)  评论(0编辑  收藏  举报