您的位置:首页 > 其它

POJ 1155 TELE 树状DP

2013-06-29 11:36 309 查看
以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<<30

struct 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;
}


 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: