poj2486(树形dp)
http://poj.org/problem?id=2486
题意:一颗树,n个点(1-n),n-1条边,每个点上有一个权值,求从1出发,走V步,最多能遍历到的权值
1 #include <iostream> 2 #include <cstring> 3 #include <vector> 4 #include <cstdio> 5 using namespace std; 6 inline int max(int a,int b) {return a>b? a:b;} 7 const int Ni = 105; 8 int n,m; 9 bool vis[Ni]; 10 int weg[Ni]; 11 int dp[2][Ni][211]; 12 vector<int> eg[Ni]; 13 void dfs(int p) 14 { 15 int i,j,k,son; 16 vis[p]=1; 17 for(i=0;i<=m;i++) 18 {dp[0][p][i]=dp[1][p][i]=weg[p];} 19 for(i=0;i<eg[p].size();i++) 20 { 21 son=eg[p][i]; 22 if(vis[son]) continue; 23 dfs(son); 24 for(j=m;j>=0;j--) 25 { 26 for(k=0;k<=j;k++) 27 { 28 //从p往son分支走得到结果回到p,人留在p 29 dp[0][p][j+2] = max(dp[0][p][j+2],dp[0][p][j-k]+dp[0][son][k]); 30 //从son往p走,再回到p的son,人留在son 31 dp[1][p][j+2] = max(dp[1][p][j+2],dp[1][p][j-k]+dp[0][son][k]); 32 //从p往son分支走得到结果 33 dp[1][p][j+1] = max(dp[1][p][j+1],dp[0][p][j-k]+dp[1][son][k]); 34 } 35 } 36 } 37 } 38 int main() 39 { 40 while(~scanf("%d%d",&n,&m)) 41 { 42 memset(vis,0,sizeof(vis)); 43 memset(dp,0,sizeof(dp)); 44 for(int i=1;i<=n;i++) 45 { 46 eg[i].clear(); 47 scanf("%d",weg+i); 48 } 49 for(int i=1;i<n;i++) 50 { 51 int u,v; 52 scanf("%d%d",&u,&v); 53 eg[u].push_back(v); 54 eg[v].push_back(u); 55 } 56 dfs(1); 57 printf("%d\n",dp[1][1][m]); 58 } 59 return 0; 60 }