【CodeVS 1163】访问艺术馆

http://codevs.cn/submission/2367697/
loli蜜汁(面向高一)树形dp是这道题的改编。
改编后的题目中每个展览厅的有多个不同的画,偷画的时间和画的价值也不同,求最大价值。
需要在叶节点上做01背包。
但codevs上的这道题就简单多了,直接改了改01背包交上去A了。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

struct nodeTreeDP {
	struct node {int nxt, to;} E[100003];
	int cnt, val[103], point[50003], f[103][603], m, tot;
	nodeTreeDP() {
		cnt = 0; tot = 1;
		memset(E, 0, sizeof(E));
		memset(f, 0, sizeof(f));
		memset(point, 0, sizeof(point));
	}
	
	void ins(int u, int v) {E[++cnt] = (node) {point[u], v}; point[u] = cnt;}
	
	void dfsread(int from) {
		int t, x;
		scanf("%d%d", &t, &x);
		++tot;
		ins(from, tot);
		val[tot] = t << 1;
		if (x) {
			int w, c; w = 1; c = 5;
			for(int i = 1; i <= x; ++i) {
				for(int j = 600; j >= 0; --j)
					if (j - (t << 1) - c >= 0)
						f[tot][j] = max(f[tot][j], f[tot][j - c] + w);
			}
		} else {
			int now = tot;
			dfsread(now);
			dfsread(now);
		}
	}
	void readin() {
		int t, x;
		scanf("%d%d", &t, &x);
		val[1] = t << 1;
		if (!x) {
			dfsread(1);
			dfsread(1);
		} else {
			int w, c; w = 1; c = 5;
			for(int i = 1; i <= x; ++i) {
				for(int j = 600; j >= 0; --j)
					if (j - (t << 1) - c >= 0)
						f[1][j] = max(f[1][j], f[1][j - c] + w);
			}
		}
	}
	
	void TreeDP(int x) {
		for(int i = point[x]; i; i = E[i].nxt)
			TreeDP(E[i].to);
		if (!point[x]) return;
		int left = 0, right = 0;
		for(int i = point[x]; i; i = E[i].nxt) {
			if (!left) left = E[i].to;
			else right = E[i].to;
		}
		for(int top = val[x]; top <= 600; ++top) {
			int res = top - val[x];
			for(int leftnum = 0; leftnum <= res; ++leftnum) {
				int rightnum = res - leftnum;
				f[x][top] = max(f[x][top], f[left][leftnum] + f[right][rightnum]);
			}
		}
	}
	void ansit() {
		TreeDP(1);
		printf("%d
", f[1][m]);
	}
} *T;

int main() {
	T = new nodeTreeDP;
	scanf("%d", &T->m);
	T->readin();
	T->ansit();
	return 0;
}
原文地址:https://www.cnblogs.com/abclzr/p/5905559.html