首页 > 代码库 > POJ 2486 树形dp
POJ 2486 树形dp
题目大意:
从 1 号点出发,每次经过一个点,就可以得到点上的所有苹果,走m步,求能够得到的苹果最大数量
这里用dp[u][j] 表示 从u号点出发走 j 步后回到u点能得到的苹果最大数量
用ans[u][j] 表示从 u 号点出发走 j 步不一定回到u点能得到的苹果最大数量(包括了dp[u][j]的情况)
因为从父亲到儿子,最后又要回到父亲需要多走2次
dp[u][j+2] = max{dp[v][k] + dp[u][j-k]} k<=j , j<=m
对于ans[][]来说因为不确定它是否回到父亲,所以根据dp[][]来算
要从一棵子树到另一棵子树,那么必然经过父亲 , 那么这两棵子树中可能是原子树回到了原点 , 那么当前子树就没必要回到原点,那么当前边只要去不用回来
ans[u][j+1] = max{ans[v][k] + dp[u][j-k]}
又可能是当前子树回到了原点 , 那么原子树就没必要回到原点,那么就是从父亲先去当前子树,再回来经过原来的子树合并,当前边来回就是多走两次
ans[u][j+2] = max{dp[v][k] + ans[u][j-k]}
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 using namespace std; 5 const int N = 205; 6 int val[N] , first[N] , k , dp[N][N] , ans[N][N]; 7 8 struct Edge{ 9 int y , next;10 }e[N<<1];11 12 void add_edge(int x, int y)13 {14 e[k].y = y , e[k].next = first[x];15 first[x] = k++;16 }17 18 void dfs(int u , int fa , int m)19 {20 ans[u][0] = dp[u][0] = val[u];21 for(int i = first[u] ; i!=-1 ; i=e[i].next){22 int v = e[i].y;23 if(v == fa) continue;24 dfs(v , u , m);25 for(int j=m ; j>=0 ; j--){26 for(int k=j ; k>=0 ; k--){27 dp[u][j+2] = max(dp[u][j+2] , dp[v][k] + dp[u][j-k]);28 ans[u][j+2] = max(dp[v][k] + ans[u][j-k] , ans[u][j+2]);29 ans[u][j+1] = max(ans[v][k] + dp[u][j-k] , ans[u][j+1]);30 }31 }32 }33 }34 35 int main()36 {37 // freopen("a.in" , "r" , stdin);38 int n,m,x,y;39 while(scanf("%d%d" , &n , &m)==2)40 {41 for(int i=1 ; i<=n ; i++)42 scanf("%d" , val+i);43 memset(first , -1 , sizeof(first));44 k = 0;45 for(int i=1 ; i<n ; i++){46 scanf("%d%d" , &x , &y);47 add_edge(x , y);48 add_edge(y , x);49 }50 memset(ans , 0 , sizeof(ans));51 memset(dp , 0 , sizeof(dp));52 53 dfs(1 , -1 , m);54 55 int maxn = 0;56 for(int i=0 ; i<=m ; i++)57 maxn = max(maxn , ans[1][i]);58 printf("%d\n" , maxn);59 }60 return 0;61 }
POJ 2486 树形dp
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。