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\n", 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\n", dp[1][t]); return 0; }
树形dp根节点虐炸1个多小时。我是把边和终点放在了一起,所以从1开始其实是对边建的树,忽略了0-1最原始的边的权重一直出不来
由于还要考虑边权值,分为只取左子树,只取右子树,两边都走的情况,虽然好像可以优化成一个forfor,但是为了稳我还是分开来背包了