POJ 1155 TELE 树状DP

来源:互联网 发布:js数组复制copy 编辑:程序博客网 时间:2024/05/23 21:05

以DP[i][j]表示以第i个点为根节点的树获得j个用户能够赚的最大值,最后查找DP[1][j]值不小于零的最大j值就是答案,注意DP的初始化,刚开始只初始了一部分,结果苦逼的Wrong了,应该所有值都要初始为最小值。

 

#include <cstdio>#include <cstring>#include <iostream>#include <queue>#include <algorithm>#include <map>#include <vector>#include <stack>using namespace std;#define M 3005#define ll unsigned long long#define int64 __int64#define inf 1<<30struct node{int cost , e;};vector<node> tree[M];int n , m , dp[M][M] , pay[M];int Dfs(int rt){dp[rt][0] = 0;if (rt > n-m) {dp[rt][1] = pay[rt];return 1;}int i , j , k , up = tree[rt].size() , sum = 0; //sum记录当前点下面的用户数量for (i = 0 ; i < up ; i++)sum += Dfs(tree[rt][i].e);for (i = 0 ; i < up ; i++){for (j = sum ; j > 0 ; j--)//若直接从m开始循环,会超时的{for (k = 1 ; k <= j ; k++){dp[rt][j] = max(dp[rt][j] , dp[tree[rt][i].e][k]+dp[rt][j-k]-tree[rt][i].cost);}}}return sum;}int main(){int i , j;while (~scanf("%d%d",&n,&m)){for (i = 1 ; i <= n-m ; i++){int k;node a;scanf("%d",&k);while (k--)scanf("%d%d",&a.e,&a.cost),tree[i].push_back(a);}for (i = n-m+1 ; i <= n ; i++)scanf("%d",pay+i);for (i = 0 ; i <= n ; i++)for (j = 0 ; j <= m ; j++)dp[i][j] = -(1<<20);Dfs(1);int ans = 0;for (i = 1 ; i <= m ; i++){if (dp[1][i] >= 0)ans = i;}printf("%d\n",ans);for (i = 0 ; i <= n ; i++)tree[i].clear();}return 0;}