POJ 2486 树形背包DP Apple Tree

设d(u, j, 0)表示在以u为根的子树中至多走k步并且最终返回u,能吃到的最多的苹果。

则有状态转移方程:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <vector>
 6 using namespace std;
 7 
 8 const int maxn = 100 + 10;
 9 const int maxk = 200 + 10;
10 int n, k;
11 
12 int a[maxn];
13 int d[maxn][maxk][2];
14 vector<int> G[maxn];
15 
16 void dfs(int u, int fa)
17 {
18     for(int i = 0; i < G[u].size(); i++)
19     {
20         int v = G[u][i];
21         if(v == fa) continue;
22         dfs(v, u);
23         for(int j = k; j >= 1; j--)
24             for(int t = 1; t <= j; t++)
25             {
26                 if(t > 1) d[u][j][0] = max(d[u][j][0], d[u][j-t][0] + d[v][t-2][0]);
27                 if(t > 1) d[u][j][1] = max(d[u][j][1], d[u][j-t][1] + d[v][t-2][0]);
28                 d[u][j][1] = max(d[u][j][1], d[u][j-t][0] + d[v][t-1][1]);
29             }
30     }
31 }
32 
33 int main()
34 {
35     while(scanf("%d%d", &n, &k) == 2 && n)
36     {
37         for(int i = 1; i <= n; i++) G[i].clear();
38         memset(d, 0, sizeof(d));
39         for(int i = 1; i <= n; i++)
40         {
41             scanf("%d", a + i);
42             for(int j = 0; j <= k; j++) d[i][j][0] = d[i][j][1] = a[i];
43         }
44         for(int i = 1; i < n; i++)
45         {
46             int u, v; scanf("%d%d", &u, &v);
47             G[u].push_back(v); G[v].push_back(u);
48         }
49 
50         dfs(1, 0);
51 
52         printf("%d
", max(d[1][k][0], d[1][k][1]));
53     }
54 
55     return 0;
56 }
代码君
原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/4692107.html