POJ 2486 Apple Tree(树DP)
题意:现有一棵苹果树,树中每个结点上都有一定数量的苹果,问若从根结点出发,最多只能走K步(每一步都只能从一个结点走到相邻结点),最多能摘多少苹果。
分析:定义dp[i][j][0],表示从 i 出发,向下走 j 步,最后回到 i 最多能摘的苹果数,dp[i][j][1]表示从 i 出发,向下走 j 步最后没有回到 i 最多能摘多少苹果。
View Code
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; #define N 101 int n,e,step,w[N]; int first[N],next[N<<1],v[N<<1]; int dp[N][N<<1][2]; void init() { e=0; memset(first+1,-1,sizeof(first[0])*n); } void add(int a,int b) { v[e]=b; next[e]=first[a]; first[a]=e++; } void dfs(int a,int fa) { memset(dp[a],0,sizeof(dp[0])); dp[a][0][0]=w[a]; int i,b; for(i=first[a]; ~i; i=next[i]) { b=v[i]; if(b==fa) continue; dfs(b,a); for(int j=step; j>=0; j--) { for(int k=0; j+k+2<=step; k+=2) { dp[a][j+k+2][1]=max(dp[a][j+k+2][1],dp[a][j][1]+dp[b][k][0]); } if(~j&1) { for(int k=0; j+k+2<=step; k+=2) { dp[a][j+k+2][0]=max(dp[a][j+k+2][0],dp[a][j][0]+dp[b][k][0]); } for(int k=0; j+k+1<=step; k++) { dp[a][j+k+1][1]=max(dp[a][j+k+1][1],dp[a][j][0]+max(dp[b][k][1],dp[b][k][0])); } } } } } int main() { int a,b; while(~scanf("%d%d",&n,&step)) { init(); for(int i=1; i<=n; i++) scanf("%d",&w[i]); for(int i=1; i<n; i++) { scanf("%d%d",&a,&b); add(a,b); add(b,a); } dfs(1,0); int ans=0; for(int j=0; j<=step; j++) ans=max(ans,max(dp[1][j][0],dp[1][j][1])); printf("%d\n",ans); } return 0; }