G - Apple Tree POJ - 2486

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

此题为三维树形dp背包

/*
给你一颗苹果树,每个节点都有相应的苹果树,让你求从结点1开始走最多走k步,能吃到的最多苹果数
*/
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<vector>
#define N 220
#define INF 0x3f3f3f3f
using namespace std;
struct node
{
    int to;
    node (int TO)
    {
        to=TO;
    };
};
int n,k;
int dp[N][N][2];//dp[u][k]表示以u为根结点,走到k步时,返不返回根节点的最多获取多少苹果
int val[N];//盛放每个点的苹果数
vector<node>edge[N];
/*
(1)不能用记忆化搜索因为可能不是最后一步取到的最大值

(2)不是一条路径走到底能吃多少苹果,这样遍历,因为虽然走过一个地方就把这个地方的苹果吃光,但是如果走完一条路径的时候还有余下的步数可以返回
再接着吃别的路径的

*/
void dfs(int u,int p)//这一步,上一部,还剩多少步;
{
    for(int i=0; i<edge[u].size(); i++)
    {
        int v=edge[u][i].to;
        if(v==p) continue;
        dfs(v,u);
        for(int j=k; j>=1; j--)
        {
            for(int k=1; k<=j; k++)
            {
                dp[u][j][0]=max(dp[u][j][0],dp[u][j-k][1]+dp[v][k-1][0]);
                //从u到v回到u,在v中遍历的时候不回来
                //不返回根节点的,顶点u只用j-k步,剩下的给v,因为由u到v要耗费一步,所以在v点的时候最多只能走k步
                dp[u][j][0]=max(dp[u][j][0],dp[u][j-k][0]+dp[v][k-2][1]);
                //从u点到v点,然后v点回来
                //不返回根节点的,顶点u只用j-k步,剩下的给v,因为由u到v,再由v到u要耗费两步,所以在v点的时候最多只能走k步
                dp[u][j][1]=max(dp[u][j][1],dp[u][j-k][1]+dp[v][k-2][1]);
                //从u点到v点,然后v点中遍历回到v,再回到u
                //返回根节点的,顶点只用j-k步,剩下的给v,因为由u到v,再由v到u要耗费两步,所以在v点的时候最多只能走k步
            }
        }
    }
}
int main()
{
    //freopen("in.txt","r",stdin);
    while(scanf("%d%d",&n,&k)!=EOF)
    {
        memset(dp,0,sizeof dp);
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&val[i]);
            for(int j=0; j<=k; j++)
            {
                dp[i][j][1]=dp[i][j][0]=val[i];//初始化
            }
            edge[i].clear();
            //cout<<val[i]<<" ";
        }
        //cout<<endl;
        int a,b;
        for(int i=1; i<n; i++)
        {
            scanf("%d%d",&a,&b);
            edge[a].push_back(b);
            edge[b].push_back(a);
        }
        dfs(1,0);
        printf("%d\n",max(dp[1][k][1],dp[1][k][0]));
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZZ --瑞 hopeACMer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值