Poj--2486(树形DP)
2014-12-09 09:41:47
思路:题目很好理解,一开始毫无思路TAT....好像树上背包可搞。
最终:dp[i][j][0] :表示从i出发,最多走j步,且最后回到i的最优解,dp[i][j][1]:表示从i出发,最多走j步,且最后不回到i的最优解。
转移:dp[i][j+2][0] = max(dp[i][j+2][0],dp[i][j - k][0] + dp[son][k][0]) (从i出发到son,并且回到i)
dp[i][j+1][1] = max(dp[i][j+1][1],dp[i][j - k][0] + dp[son][k][1]) (从i出发到son,不会到i,那么遍历除son外其他子节点时继续回到i (dp[i][j - k][0]))
dp[i][j+2][1] = max(dp[i][j+2][1],dp[i][j - k][1] + dp[son][k][0]) (从i出发到son,并且回到i,然后再出发到其他儿子,最终不回i)
1 /************************************************************************* 2 > File Name: 2486.cpp 3 > Author: Natureal 4 > Mail: 564374850@qq.com 5 > Created Time: Tue 09 Dec 2014 01:21:00 AM CST 6 ************************************************************************/ 7 8 #include <cstdio> 9 #include <cstring> 10 #include <cstdlib> 11 #include <cmath> 12 #include <vector> 13 #include <map> 14 #include <set> 15 #include <stack> 16 #include <queue> 17 #include <iostream> 18 #include <algorithm> 19 using namespace std; 20 #define lp (p << 1) 21 #define rp (p << 1|1) 22 #define getmid(l,r) (l + (r - l) / 2) 23 #define MP(a,b) make_pair(a,b) 24 typedef long long ll; 25 const int INF = 1 << 30; 26 const int maxn = 210; 27 28 int N,K; 29 int num[maxn]; 30 int first[maxn],next[maxn * 2],ver[maxn * 2],ecnt; 31 int dp[maxn][maxn * 2][2]; 32 33 void Init(){ 34 memset(dp,0,sizeof(dp)); 35 memset(first,-1,sizeof(first)); 36 ecnt = 0; 37 } 38 39 void Add_edge(int u,int v){ 40 next[++ecnt] = first[u]; 41 ver[ecnt] = v; 42 first[u] = ecnt; 43 } 44 45 void Solve(int fa,int p){ 46 for(int i = first[p]; i != -1; i = next[i]){ 47 int v = ver[i]; 48 if(v == fa) 49 continue; 50 Solve(p,v); 51 for(int j = K - 1; j >= 0; --j){ 52 for(int k = 0; k <= j; ++k){ 53 if(j + 2 <= K){ 54 dp[p][j + 2][0] = max(dp[p][j + 2][0],dp[p][j - k][0] + dp[v][k][0]); 55 //留在其他son里 56 dp[p][j + 2][1] = max(dp[p][j + 2][1],dp[p][j - k][1] + dp[v][k][0]); 57 } 58 dp[p][j + 1][1] = max(dp[p][j + 1][1],dp[p][j - k][0] + dp[v][k][1]); 59 } 60 //printf("liu %d , qita %d , ziji %d\n",dp[p][j + 2][0],dp[p][j + 2][1],dp[p][j + 1][1]); 61 } 62 } 63 } 64 65 int main(){ 66 int a,b; 67 while(scanf("%d%d",&N,&K) != EOF){ 68 Init(); 69 for(int i = 1; i <= N; ++i){ 70 scanf("%d",num + i); 71 for(int j = 0; j <= K; ++j){ 72 dp[i][j][0] = dp[i][j][1] = num[i]; 73 } 74 } 75 for(int i = 1; i < N; ++i){ 76 scanf("%d%d",&a,&b); 77 Add_edge(a,b); 78 Add_edge(b,a); 79 } 80 Solve(0,1); 81 printf("%d\n",max(dp[1][K][0],dp[1][K][1])); 82 } 83 return 0; 84 }