http://hihocoder.com/problemset/problem/1500
题意理解:一棵树,父亲只有在直接儿子被干掉的权重和大于某个数才能都被干掉,并且干掉一个点需要若干时间。权重《=20000, 节点《=2000,可以每一个节点都用裸的01背包做,注意背包容量可以超过,最后取min
急转弯:数据范围小,可以裸着做,另外注意min的取法。
算法:无
数据结构:树,但是和树的数据结构没有关系,只是用到了树的先考虑儿子,再考虑父亲的遍历(dfs)
注:python版本t了。。尴尬。。有好的优化希望能告诉我!
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
const int maxn = 2000 + 100;
const int MAXK = 20000 + 100;
const int INF = 1e7;
int need[maxn], have[maxn], tim[maxn];
int n, rt;
vector<int> G[maxn];
int dfs(int u) {
if(G[u].size() == 0) return tim[u];
int f[MAXK];
f[0] = 0;
for(int i = 1; i < MAXK; i++) f[i] = INF;
for(int i = 0; i < G[u].size(); i++){
int v = G[u][i];
int t = dfs(v);
for(int j = need[u] - 1; j >= 0; j--) {
int no = min(MAXK - 1, j + have[v]);
f[no] = min(INF, min(f[no], f[j] + t));
}
}
int res = INF;
for(int i = need[u]; i < MAXK; i++) res = min(res, f[i]);
return res + tim[u];
}
int main() {
scanf("%d", &n);
rt = 1;
for(int i = 1; i <= n; i++) G[i].clear();
for(int i = 1; i <= n; i++) {
int a, b, c, d;
scanf("%d%d%d%d", &a, &b, &c, &d);
if(a == 0){
rt = i;
} else{
G[a].push_back(i);
}
need[i] = b;
have[i] = c;
tim[i] = d;
}
int res = dfs(rt);
if(res < INF) printf("%d\n", res);
else printf("-1");
}
from __future__ import print_function # # 'python for tree and easy dp' __author__ = 'hjkruclion' import sys def read_int(): return list(map(int, sys.stdin.readline().split())) MAXN = 20000 + 10 INF = int(1e7) MAXP = 2000 + 100 G = [[]for _ in range(MAXP)] # need = np.zeros([MAXP], np.int) # have = np.zeros([MAXP], np.int) # time = np.zeros([MAXP], np.int) need = [0 for _ in range(MAXP)] have = [0 for _ in range(MAXP)] time = [0 for _ in range(MAXP)] dp = [0 for _ in range(MAXP)] f = [0 for _ in range(MAXN + 10)] rt = 1 N = read_int()[0] for i in range(1, N + 1): fa, iN, ip, c = read_int() if fa != 0: G[fa].append(i) else: rt = i need[i] = iN have[i] = ip time[i] = c def dfs(u): if len(G[u]) == 0: return time[u] # f = np.zeros([MAXN + 10], np.int) for i in range(len(G[u])): v = G[u][i] dp[v] = dfs(v) global f f[0] = 0 for i in range(1, MAXN): f[i] = INF for i in range(len(G[u])): v = G[u][i] t = dp[v] for j in reversed(range(need[u])): no = min(need[u], j + have[v]) f[no] = min(INF, min(f[no], f[j] + t)) res = f[need[u]] return min(INF, res + time[u]) res = dfs(rt) if res < INF: print(res) else: print('-1')