1. 程式人生 > >poj 1155 TELE 樹形揹包dp

poj 1155 TELE 樹形揹包dp

dp[i][we] 代表節點為i 給k個消費者提供訊號的所賺錢術 這時we就是揹包容量,每個子節點的每個dp[son][j] 0 <=j<= num[j]; 就是各個物品了

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#define mini -100000000
#define maxn 3005
using namespace std;
int dp[maxn][maxn], n, m, va[maxn], num[maxn];
int last[maxn * 2
], Next[maxn * 2], edge[maxn * 2], cost[maxn * 2], l; void add(int a, int b, int va) { edge[l] = b; cost[l] = va; Next[l] = last[a]; last[a] = l; l++; } void dfs(int pre) { for(int i = last[pre]; i != -1; i = Next[i]) { dfs(edge[i]); num[pre] += num[edge[i]]; for
(int j = num[pre]; j >= 0; j--) for(int k = min(j ,num[edge[i]]); k >= 0; k--) dp[pre][j] = max(dp[pre][j], dp[edge[i]][k] + dp[pre][j - k] - cost[i]); } } int main() { while(scanf("%d%d", &n, &m)!=EOF) { l = 0; memset(last, -1, sizeof
(last)); for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) dp[i][j] = mini; for(int i = 1; i<= n - m; i++) { num[i] = 0; int k; scanf("%d", &k); while(k--) { int a, b, c; scanf("%d%d", &a, &b); add(i, a, b); } } for(int i = n - m + 1; i <= n; i++) { num[i] = 1; scanf("%d", &dp[i][1]); } dfs(1); for(int i = m; i >= 0; i--) if(dp[1][i] >= 0) {printf("%d\n", i); break;} } return 0; }