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