Apple Tree POJ

题目链接:

D - 树形dp

 POJ - 2486 

题目大意:一颗树,n个点(1-n),n-1条边,每个点上有一个权值,求从1出发,走V步,最多能遍历到的权值

学习网址:https://blog.csdn.net/Aria461863631/article/details/82356420

具体思路:

dp[root][j][0]为从root出发,走j步并且最终回到原来点(中间也有可能回到原来的点,但是会继续往下走)的情况下,回到root节点的权值最大值。

dp[root][j][1]为从root出发,走j步并且最终不会到原来点(中间也有可能回到原来的点,但是会继续往下走)的情况下,回到root节点的权值最大值。

dp[root][j][0]=max(dp[root][j][0],dp[root][j-i][0]+dp[son][i-2][0]);

从当前的root出发,先计算从root开始走j-i步并且回到root的时候(遍历其他子树)的最大值,再加上走当前的son节点并且回来的时候最大值,

之所以是i-2的原因是,从s出发到t,然后从t再回到s,这一共是额外的两步,所以是i-2。

dp[root][j][1]=max(dp[root][j][1],dp[root][j-i][0]+dp[son][i-1][1]);

从当前的root出发,先计算从root出发走j-i步并且回到root的时候(遍历其他的子树)的最大值,在加上到达son,并且从son出发,不再回到root节点的最大值。

dp[root][j][1]=max(dp[root][j][1],dp[root][j-i][1]+dp[son][i-2][0]);

从当前root节点出发,先计算从root到son节点走i-2步并且回到root的时候的最大值,然后再去从root节点出发,到达剩余子树并且最终不回到root节点的最大值。

AC代码:

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include<string>
 6 #include<cstring>
 7 #include<vector>
 8 using namespace std;
 9 # define ll long long
10 const int maxn = 2e5+100;
11 # define inf 0x3f3f3f3f
12 int dp[200+10][200+10][2];
13 int vis[maxn];
14 int sto[maxn];
15 vector<int>Edge[maxn];
16 int n,k;
17 void init()
18 {
19     for(int i=0; i<=n; i++)
20     {
21         vis[i]=0;
22         Edge[i].clear();
23 //        for(int j=0; j<=k; j++)
24 //        {
25 //            dp[i][j][0]=0;
26 //            dp[i][j][1]=0;
27 //        }
28     }
29 }
30 void dfs(int  u,int dep)
31 {
32     for(int i=0; i<=k; i++)
33     {
34         dp[u][i][0]=dp[u][i][1]=sto[u];
35     }
36     vis[u]=1;
37     for(int i=0; i<Edge[u].size(); i++)
38     {
39         int to=Edge[u][i];
40         if(vis[to])
41             continue;
42         dfs(to,dep-1);
43         for(int i1=k; i1>=1; i1--)
44         {
45             for(int i2=1; i2<=i1; i2++)
46                 
47             {
48                   if(i2-2>=0)
49                     dp[u][i1][0]=max(dp[u][i1][0],
50                                      dp[u][i1-i2][0]+dp[to][i2-2][0]);
51                 if(i2-1>=0)
52                     dp[u][i1][1]=max(dp[u][i1][1],
53                                      dp[u][i1-i2][0]+dp[to][i2-1][1]);
54                 if(i2-2>=0)
55                     dp[u][i1][1]=max(dp[u][i1][1],
56                                      dp[u][i1-i2][1]+dp[to][i2-2][0]);
57             }
58         }
59     }
60 }
61 int main()
62 {
63     while(~scanf("%d %d",&n,&k)){
64         int st,ed;
65         init();
66         for(int i=1; i<=n; i++){
67             scanf("%d",&sto[i]);
68         }
69         for(int i=1; i<n; i++){
70             scanf("%d %d",&st,&ed);
71             Edge[st].push_back(ed);
72             Edge[ed].push_back(st);
73         }
74         dfs(1,k);
75         printf("%d
",max(dp[1][k][1],dp[1][k][0]));
76     }
77     return 0;
78 }