题目链接:
D - 树形dp
题目大意:一颗树,n个点(1-n),n-1条边,每个点上有一个权值,求从1出发,走V步,最多能遍历到的权值
学习网址:https://blog.csdn.net/Aria461863631/article/details/82356420
具体思路:dp[i][j][0]代表当前的i点在只走一边的情况下,往下走j部最多能获得的权值。
dp[i][j][1]代表当前的点在两边都走的情况下,往下走j不最多能获得的权值。
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\n",max(dp[1][k][1],dp[1][k][0]));
76 }
77 return 0;
78 }