zoukankan      html  css  js  c++  java
  • 【POJ 2486】 Apple Tree(树型dp)

    【POJ 2486】 Apple Tree(树型dp)

    Time Limit: 1000MS   Memory Limit: 65536K
    Total Submissions: 8981   Accepted: 2990

    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


    难得1A 不枉这两天跟树dp天天见。

    题目大意:一棵树。

    。。

    还是一棵树……每一个节点有一个点权。从树根出发,最远走k步,每走到一个新点。能够把该点的权值累加进去,问最多能够走出多大的权值和。

    比較裸的树dp了。dp[i][j][0/1]表示根节点i開始走j步能够走出的最大权值和。近期做树型dp蛮多。发现大多都是这样。要开两个三维空间。一个表示答案。一个是用来辅助求解的。

    此题相同,0表示走j步不回到根。1表示终于回到根。


    这样发现每一个u来说。新遍历到一个孩子v,

    dp[u][i][1]的更新为dp[u][i-j-2][1]+dp[v][j][1] 也就是说加上u到v这一步和从v遍历完返回u的v到u这步还有从v出发j步回到v 组成i

    dp[u][i][0]的更新有两种,一种是到v后往后走完不回根 dp[u][i][0] = dp[u][i-j-1][1]+dp[v][j][0]

    一种是v往后走完回根。然后从之前某个节点走完不回根 dp[u][i][0] = dp[u][i-j-2][0]+dp[v][j][1]


    当然 上面这些都要取最大


    代码例如以下:

    #include <iostream>
    #include <cmath>
    #include <vector>
    #include <cstdlib>
    #include <cstdio>
    #include <cstring>
    #include <queue>
    #include <stack>
    #include <list>
    #include <algorithm>
    #include <map>
    #include <set>
    #define LL long long
    #define Pr pair<int,int>
    #define fread() freopen("in.in","r",stdin)
    #define fwrite() freopen("out.out","w",stdout)
    
    using namespace std;
    const int INF = 0x3f3f3f3f;
    const int msz = 10000;
    const int mod = 1e9+7;
    const double eps = 1e-8;
    
    bool mp[111][111];
    //0不回 1回
    int dp[111][222][2];
    int n,k;
    int val[111];
    
    void dfs(int u,int pre)
    {
    	dp[u][0][0] = dp[u][0][1] = val[u];
    	for(int v = 1; v <= n; ++v)
    	{
    		if(v == pre || !mp[u][v]) continue;
    		dfs(v,u);
    		for(int i = k; i > 0; --i)
    		{
    			for(int j = 0; j < i; ++j)
    			{
    				if(j+2 <= i) 
    				{
    					dp[u][i][1] = max(dp[u][i][1],dp[u][i-j-2][1]+dp[v][j][1]);
    					dp[u][i][0] = max(dp[u][i][0],dp[u][i-j-2][0]+dp[v][j][1]);
    				}
    				dp[u][i][0] = max(dp[u][i][0],dp[u][i-j-1][1]+dp[v][j][0]);
    			}
    		}
    	}
    }
    
    int main()
    {
    	//fread();
    	//fwrite();
    
    	int u,v;
    	while(~scanf("%d%d",&n,&k))
    	{
    		memset(mp,0,sizeof(mp));
    		for(int i = 1; i <= n; ++i)
    			scanf("%d",&val[i]);
    		for(int i = 1; i < n; ++i)
    		{
    			scanf("%d%d",&u,&v);
    			mp[u][v] = mp[v][u] = 1;
    		}
    		memset(dp,0,sizeof(dp));
    		dfs(1,1);
    		int id = k;
    		while(id && !dp[1][id][0]) --id;
    		printf("%d
    ",dp[1][id][0]);
    	}
    
    	return 0;
    }
    
    






  • 相关阅读:
    KVM(Keyboard、Video、Mouse)
    javascript valueof
    javascript的typeof的返回值
    javascript的===和==
    WGestures全局鼠标手势工具
    向win+x快捷目录添加功能
    好用的影子系统软件
    备份任务栏
    修改多个调用提示最小值_改变多选右键菜单
    执行Windows Update更新
  • 原文地址:https://www.cnblogs.com/mthoutai/p/7098020.html
Copyright © 2011-2022 走看看