Description
Input
Each test case contains three parts.
The first part is two numbers N K, whose meanings we have talked about just now. We denote the nodes by 1 2 ... N. Since it is a tree, each node can reach any other in only one route. (1<=N<=100, 0<=K<=200)
The second part contains N integers (All integers are nonnegative and not bigger than 1000). The ith number is the amount of apples in Node i.
The third part contains N-1 line. There are two numbers A,B in each line, meaning that Node A and Node B are adjacent.
Input will be ended by the end of file.
Note: Wshxzt starts at Node 1.
Output
Sample Input
2 1 0 11 1 2 3 2 0 1 2 1 2 1 3
Sample Output
11 2
题意:
有N个点构成的树,每个点有一定价值。现在一个人从1点开始走,最多走K步(1步一条边。可以走重复边)。求最大价值。
分析:树形DP。
dp[ x ] [ y ] [ 0/1] 表示从X点开始走Y步然后(0:回到X点,1:不回到X点)的最大价值。
然后状态转移就是
dp[ x ] [ y + 2 ] [ 0 ] = max(dp[ x ][ y + 2 ] [ 0 ] , dp[ x ] [ y - k ][ 0 ] + dp[ son ] [ k ][ 0 ] ) son 是 x 的 儿子.之所以y 要+2.是因为还要算上 y 到 son 往返的两次。
dp[ x ] [ y + 2 ] [ 1 ] = max(dp[ x ][ y + 2 ] [ 1 ] , dp[ x ] [ y - k ][ 1 ] + dp[ son ] [ k ][ 0 ] ) son 是 x 的 儿子.之所以y 要+2.是因为还要算上 y 到 son 往返的两次。
dp[ x ] [ y + 1 ] [ 1 ] = max(dp[ x ][ y + 1 ] [ 1 ] , dp[ x ] [ y - k ][ 0 ] + dp[ son ] [ k ][ 1 ] ) son 是 x 的 儿子.之所以y 要+1.是因为 son 不用返回所以只需要经过 y - son 一次。
注意:
双向边!
代码:
#include <stdio.h>
#include <string.h>
#include <vector>
using namespace std;
int dp[110][210][2];
vector<int>edge[110];
int w[110];
int n,m;
void dfs(int x,int pre)
{
for(int i = 0 ; i <= m ; i ++)
dp[x][i][0] = dp[x][i][1] = w[x];
for(int i = 0 ; i < edge[x].size() ; i++)
{
int y = edge[x][i];
if(y == pre) continue;
dfs(y,x);
for(int j = m ; j >= 0 ; j --)
{
for(int k = 0 ; k <= j ; k ++)
{
dp[x][j+2][0] = max(dp[x][j+2][0],dp[x][j-k][0]+dp[y][k][0]);
dp[x][j+2][1] = max(dp[x][j+2][1],dp[x][j-k][1]+dp[y][k][0]);
dp[x][j+1][1] = max(dp[x][j+1][1],dp[x][j-k][0]+dp[y][k][1]);
}
}
}
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
int u,v;
for(int i = 0 ; i <= n ; i ++)edge[i].clear();
for(int i = 1 ; i <= n ; i ++)scanf("%d",&w[i]);
for(int i = 1 ; i < n ; i ++)
{
scanf("%d%d",&u,&v);
edge[u].push_back(v);
edge[v].push_back(u);
}
dfs(1,0);
printf("%d\n",max(dp[1][m][0],dp[1][m][1]));
}
return 0;
}