P1270

#include <stdio.h>
#include <algorithm>

using namespace std;

#define lc(i) i<<1
#define rc(i) i<<1|1
typedef long long ll;
const int maxn = 1e6+10;
const int inf = 0x3f3f3f3f;
int t;
struct enode {
    int w, num;
}edge[300];
int tot;
int dp[300][600];
int x, y;
void Build(int rt) {
//    printf("    rt = %d
", rt);
    scanf("%d%d", &x, &y);
    edge[rt].w = 2*x;
    if (y == 0) {
        Build(lc(rt));
        Build(rc(rt));
        edge[rt].num = 0;
    } else {
        edge[rt].num = y;
    }
}
void dfs(int rt) {
    if (edge[rt].num) {
        for (int i = 0; i <= t; i++) {
            dp[rt][i] = min(i / 5, edge[rt].num);
        }
        return;
    }
    dfs(lc(rt));
    dfs(rc(rt));
    if (rt == 1) t -= edge[rt].w;
    for (int i = max(0, t-edge[lc(rt)].w); i; i--) {
        dp[rt][i+edge[lc(rt)].w] = max(dp[rt][i+edge[lc(rt)].w], dp[lc(rt)][i]);
    }
    for (int i = max(0, t-edge[rc(rt)].w); i; i--) {
        dp[rt][i+edge[rc(rt)].w] = max(dp[rt][i+edge[rc(rt)].w], dp[rc(rt)][i]);
    }
    for (int i = max(0, t-edge[rc(rt)].w-edge[lc(rt)].w); i; i--) {
        for (int j = 1; j < i; j++) {
            dp[rt][i+edge[rc(rt)].w+edge[lc(rt)].w] = max(dp[rt][i+edge[rc(rt)].w+edge[lc(rt)].w], dp[rc(rt)][i-j] + dp[lc(rt)][j]);
        }
    }
    return;
}
int main () {
    int n;
    scanf("%d", &t);
    t--;
    Build(1);
    dfs(1)
    printf("%d
", dp[1][t]);
    return 0;
} 

树形dp根节点虐炸1个多小时。我是把边和终点放在了一起,所以从1开始其实是对边建的树,忽略了0-1最原始的边的权重一直出不来

由于还要考虑边权值,分为只取左子树,只取右子树,两边都走的情况,虽然好像可以优化成一个forfor,但是为了稳我还是分开来背包了

原文地址:https://www.cnblogs.com/Urchin-C/p/11687769.html