POJ 2486 Apple Tree 树形DP

题意:Wshxzt从根节点1开始在苹果树上游历,树上的每个节点都会存在apple[i]个苹果,从一个节点到它的邻节点耗费步数1。现在Wshxzt可以步行step步,求她可以得到的最大苹果数量。
题解:dp[0][i][j]表示以i为根节点步行j步,且最终回到i,可以得到的最大苹果数量。dp[1][i][j]表示最终不回到i可以得到的最大苹果数量。


#include 
using namespace std;

#define N 105
#define K 205
#define max(a,b) (a>b?a:b)

int apple[N], dp[2][N][K];
int next[N][N], cnt[N];
bool vis[N];
int n, step;

void dfs ( int u )
{
	int i, j, k, v;
	for ( i = 0; i <= step; i++ )
		dp[0][u][i] = dp[1][u][i] = apple[u];

	vis[u] = 1;
	for ( i = 1; i <= cnt[u]; i++ )
	{
		v = next[u][i];
		if ( ! vis[v] )
		{
			dfs ( v );
			for ( j = step; j >= 0; j-- )
				for ( k = 0; k <= j; k++ )
				{
/* 从根节点u走到v要耗费一步,若要从v回到u又需要再耗费一步 */
					dp[0][u][j+2] = max(dp[0][u][j+2],dp[0][v][k]+dp[0][u][j-k]);
					dp[1][u][j+2] = max(dp[1][u][j+2],dp[0][v][k]+dp[1][u][j-k]);
					dp[1][u][j+1] = max(dp[1][u][j+1],dp[1][v][k]+dp[0][u][j-k]);
				}
		}
	}
}

int main()
{
	//freopen("a.txt","r",stdin);
	while ( scanf("%d %d",&n,&step) != EOF )
	{
		memset(dp,0,sizeof(dp));
		memset(next,0,sizeof(next));
		memset(cnt,0,sizeof(cnt));
		memset(vis,0,sizeof(vis));

		int i, u, v;
		for ( i = 1; i <= n; i++ )
			scanf("%d",&apple[i]);

		for ( i = 1; i < n; i++ )
		{
			scanf("%d %d",&u,&v);
			next[u][++cnt[u]] = v;
			next[v][++cnt[v]] = u;
		}
		dfs ( 1 );
		printf("%d\n",dp[1][1][step]);
	}
	return 0;
}


你可能感兴趣的:(动态规划)