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')