POJ 2486 树型dp 入门题

从根走k步获得的最大权值。

感觉情况不容易弄全。而步数从大到小有种背包的感觉。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <string>
#include <vector>

using namespace std;
int dp[210][410][3];//0是回,1是不回
int val[210],k,n;
vector<int>edge[210];
void dfs(int u,int fa)
{
    for (int i=0;i<edge[u].size();i++)
    {
        int son=edge[u][i];
        if (son==fa) continue;
        dfs(son,u);
        for (int v=k;v>=0;v--)
        {
            for (int j=0;j<=v;j++)
            {
                dp[u][v][0]=max(dp[u][v][0],dp[u][v-j][0]+dp[son][j-2][0]);
                dp[u][v][1]=max(dp[u][v][1],dp[u][v-j][0]+dp[son][j-1][1]);
                dp[u][v][1]=max(dp[u][v][1],dp[u][v-j][1]+dp[son][j-2][0]);
            }
        }
    }
}
int main()
{
    while (scanf ("%d%d",&n,&k)!=EOF)
    {
        for (int i=0;i<205;i++)
            edge[i].clear();
        for (int i=1;i<=n;i++)
        {
            scanf ("%d",&val[i]);
            for (int j=0;j<=k;j++)
            {
                dp[i][j][0]=dp[i][j][1]=val[i];
            }
        }
        for (int i=0;i<n-1;i++)
        {
            int t1,t2;
            scanf ("%d%d",&t1,&t2);
            edge[t1].push_back(t2);
            edge[t2].push_back(t1);
        }
        dfs(1,0);
        printf ("%d\n",max(dp[1][k][0],dp[1][k][1]));
    }
    return 0;
}
时间: 2024-10-26 16:20:40

POJ 2486 树型dp 入门题的相关文章

poj 3254 状压dp入门题

1.poj 3254  Corn Fields    状态压缩dp入门题 2.总结:二进制实在巧妙,以前从来没想过可以这样用. 题意:n行m列,1表示肥沃,0表示贫瘠,把牛放在肥沃处,要求所有牛不能相邻,求有多少种放法. #include<iostream> #include<cstring> #include<cmath> #include<queue> #include<algorithm> #include<cstdio> #d

没有上司的舞会——树状DP 入门题,真的比想象中简单许多

本来线性DP 都不怎么有信心,可以说学得非常差,于是下意识地觉得树状的肯定超过了我的理解能力,然后做这题的时候就直接翻了题解,哪知道这么简单……简直比01 背包还好理解啊,看来以后不能总是看到算法标签就退避了. 1 #include<iostream> 2 #include<cstdio> 3 #include<vector> 4 using namespace std; 5 const int N=10086; 6 int n,val[N]; 7 int f[N][4

POJ 1463 树型DP

链接: http://poj.org/problem?id=1463 题意: 求一棵树的最小点覆盖 题解: dp[i][0].dp[i][1]分别表示不在i结点上和在i结点上放置士兵时整个以i结点为根的子树被覆盖用到用到目标的最少数量 状态转移: 对叶子结点,有dp[i][0]=0,dp[i][1]=1 (也是递归的出口) 对非叶子结点,有 dp[i][0]=∑(dp[i][1]) dp[i][1]=∑(min(dp[j][0],dp[j][1]))+1 (j为i的子结点) 代码: 31 int

HDU1561 The more, The Better(树型DP)

题目是有n个存有宝藏的城堡,攻克任何一个城堡都需要先攻克0个或其他1个城堡,问攻克m个城堡最多能得到多少宝藏. 题目给的城堡形成一个森林,添加一个超级根把森林连在一起就是树了,那么就考虑用树型DP: dp[u][m]表示以u结点为根的子树攻克m个结点的最大价值 但是这样转移太难了,根是从每个孩子通过各自分配若干的城堡去攻克转移的,一个排列组合数,阶乘,是指数级的时间复杂度! 看了题解,原来这是依赖背包,没看背包九讲..不过网上的博客似乎没说清楚,事实上这个状态应该是三个维度来表示: dp[u][

【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

POJ 1947 树形DP入门题

给出N个点,N-1个关系,建出树形图,问最少减去几个边能得到节点数为P的树.典型树形DP题 dp[cur][j] :记录cur结点,要得到一棵j个节点的子树去掉的最少边数 转移方程用的背包的思想 对当前树的每一个子树进行计算 砍掉此子树:   dp[cur][j]=dp[cur][j]+1; 不砍掉:           for (l=0;l<=j;l++)  dp[cur][j]=Min(dp[cur][j],dp[cur][l]+dp[next][j-l]); 枚举从该树中留l个节点其他由新

POJ 3342 树形DP入门题

题目意思和POJ2342一样,只是多加了一个条件,如果最大方案数唯一,输出Yes,不唯一输出No dp的是时候多加一个变量记录答案是否唯一即可 #include "stdio.h" #include "string.h" #include "vector" using namespace std; struct node { int fa; vector<int>child; }data[210]; struct comp { int

POJ 2342 树形DP入门题

有一个大学的庆典晚会,想邀请一些在大学任职的人来参加,每个人有自己的搞笑值,但是现在遇到一个问题就是如果两个人之间有直接的上下级关系,那么他们中只能有一个来参加,求请来一部分人之后,搞笑值的最大是多少. 树形DP入门题. DP部分: dp[i][0]表示职员i不来参加party,以i为根的子树的最大搞笑值, dp[i][1]表示职员i来参加party,以i为根的子树的最大搞笑值. 转移方程: dp[cur][1]+=dp[next][0]; dp[cur][0]+=Max(dp[next][1]

HDU_1561_The more, The Better_树型dp

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1561 The more, The Better Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 7031    Accepted Submission(s): 4121 Problem Description ACboy很喜欢玩一种战略游戏,