`
473687880
  • 浏览: 487265 次
文章分类
社区版块
存档分类
最新评论

poj 2486 Apple Tree(经典树形DP)

 
阅读更多
Apple Tree
Time Limit:1000MS Memory Limit:65536K
Total Submissions:6431 Accepted:2109

Description

Wshxzt is a lovely girl. She likes apple very much. One day HX takes her to an apple tree. There are N nodes in the tree. Each node has an amount of apples. Wshxzt starts her happy trip at one node. She can eat up all the apples in the nodes she reaches. HX is a kind guy. He knows that eating too many can make the lovely girl become fat. So he doesn’t allow Wshxzt to go more than K steps in the tree. It costs one step when she goes from one node to another adjacent node. Wshxzt likes apple very much. So she wants to eat as many as she can. Can you tell how many apples she can eat in at most K steps.

Input

There are several test cases in the input
Each test case contains three parts.
The first part is two numbers N K, whose meanings we have talked about just now. We denote the nodes by 1 2 ... N. Since it is a tree, each node can reach any other in only one route. (1<=N<=100, 0<=K<=200)
The second part contains N integers (All integers are nonnegative and not bigger than 1000). The ith number is the amount of apples in Node i.
The third part contains N-1 line. There are two numbers A,B in each line, meaning that Node A and Node B are adjacent.
Input will be ended by the end of file.

Note: Wshxzt starts at Node 1.

Output

For each test case, output the maximal numbers of apples Wshxzt can eat at a line.

Sample Input

2 1 
0 11
1 2
3 2
0 1 2
1 2
1 3

Sample Output

11
2

Source

POJ Contest,Author:magicpig@ZSU

题意

给你一颗苹果树,有N个节点每个节点上都有一定数目的苹果也就是有一个权值,当你经过这个节点时你将得到这个权值,重复走节点是只能算一次,给你N-1条边。问你只能走K步能得到的最大权值和。

思路:

应该这算树形DP的一类经典应用了吧。这题难点在于可以往返走。如果没有吧状态划分好将很难做出来。

状态想出来就简单了。

dp[1][u][i]表示。从节点u出发走j步并回到u点能获得的最大苹果个数。

dp[0][u][i]表示。从节点u出发走j步不回到u点能获得的最大苹果个数。

那么就很好递推了。

详细见代码:

#include <iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
const int maxn=150;
struct node
{
    int v;
    node *next;
} edge[maxn<<1],*head[maxn];
int n,m,cnt,dp[2][maxn][maxn<<1];//注意步数上限.每条边最多走两次。
int app[maxn];
void adde(int u,int v)
{
    edge[cnt].v=v;
    edge[cnt].next=head[u];
    head[u]=&edge[cnt++];
}
void dfs(int fa,int u)
{
    int i,j,v;
    node *p;
    dp[1][u][0]=app[u];
    for(i=1;i<=m;i++)
        dp[0][u][i]=dp[1][u][i]=app[u];
    for(p=head[u];p!=NULL;p=p->next)
    {
        v=p->v;
        if(v==fa)
            continue;
        dfs(u,v);
        for(i=m;i>=0;i--)//01背包。从大到小装
        {
            for(j=0;j+2<=i;j++)
            {
                dp[1][u][i]=max(dp[1][u][i],dp[1][u][j]+dp[1][v][i-j-2]);//要回到u结点
                dp[0][u][i]=max(dp[0][u][i],dp[1][u][j]+dp[0][v][i-j-1]);//不回到u结点。停留在v的儿子结点
                dp[0][u][i]=max(dp[0][u][i],dp[1][u][j]+dp[1][v][i-j-1]);//不回到u结点。停留在v结点
                dp[0][u][i]=max(dp[0][u][i],dp[0][u][j]+dp[1][v][i-j-2]);//不回到u结点。停留在u以前儿子结点
            }
            if(j+1<=i)//注意范围
            {
                dp[0][u][i]=max(dp[0][u][i],dp[1][u][j]+dp[0][v][i-j-1]);
                dp[0][u][i]=max(dp[0][u][i],dp[1][u][j]+dp[1][v][i-j-1]);
            }
        }
    }
}
int main()
{
    int i,u,v,ans;

    while(~scanf("%d%d",&n,&m))
    {
        cnt=0;
        memset(head,0,sizeof head);
        memset(dp,0,sizeof dp);
        for(i=1;i<=n;i++)
            scanf("%d",app+i);
        for(i=1;i<n;i++)
        {
            scanf("%d%d",&u,&v);
            adde(u,v);
            adde(v,u);
        }
        dfs(1,1);
        ans=max(dp[0][1][m],dp[1][1][m]);//取回来和不回来的最大值
        printf("%d\n",ans);
    }
    return 0;
}


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics