Description
Wshxzt is a lovely girl. She likes apple very much. One day HX takes her to an apple tree. There are N nodes in the tree. Each node has an amount of apples. Wshxzt starts her happy trip at one node. She can eat up all the apples in the nodes she reaches. HX is a kind guy. He knows that eating too many can make the lovely girl become fat. So he doesn’t allow Wshxzt to go more than K steps in the tree. It costs one step when she goes from one node to another adjacent node. Wshxzt likes apple very much. So she wants to eat as many as she can. Can you tell how many apples she can eat in at most K steps.
Input
There are several test cases in the 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
For each test case, output the maximal numbers of apples Wshxzt can eat at a line.
Sample Input
2 1
0 11
1 2
3 2
0 1 2
1 2
1 3
Sample Output
11
2
这个题主要在于一个步数的分配问题…因此状态转移方程比较难理解….
给了K步,你不仅可以走入子树,还可以从子树中走出来。但是同一个节点只有第一次走过来的时候会得到他的权值。
其他的时候只能起到一个桥梁的作用。
在每一次的dfs中,每一个对应的子树都是独立的
因此其他的树所有的步数就都在 q-w中了
然后他的状态转移从高阶转移到低阶的原因是
他状态转移的和自己有关
如果他从小到大进行转移的话
那么
dp[gen][q + 2][0]
这一部分会不停地变大
有些类似于完全背包的那种
然而实际上不是..
这个树的每个节点只能够取一次
是01背包的思想
因此这个状态转移将从大到小来进行转移
便于和其他子树的状态进行比较
然后是状态转移方程
因为每个子树在对自己进行dfs的时候都是独特的
因此q-w已经把每颗子树的多余的东西算进去了
然后再看转移
对于这棵树,他的走路大概有这么几种可能
1.从树根走到叶子
2.从树根走到一棵子树的某个节点再走回去走到树根
再次从树根走出来
问题就在于这里
正常情况下一条路只能够走一次
而返回当作桥梁的情况就不是这样了
当他从当前子树走去其他子树的时候他每一步对于走入其他子树都是多余的。
dp[gen][q+2][0]是对于离开当前树去其他的树所采用的情况
dp[gen][q+2][1]和dp[gen][q+1][1]则是一种互相补充的状态转移
#include<iostream>
#include<algorithm>
#include<vector>
#include<cstdio>
using namespace std;
int dp[101][301][2],n,k,biaoji[101],zhi[101];
vector<int> li[101];
void maxi(int &a, int b)
{
if (a < b)a = b;
}
void dfs(int gen)
{
biaoji[gen] = 1;
for (int a = 0; a < li[gen].size(); a++)
{
if (biaoji[li[gen][a]] == 0)
{
dfs(li[gen][a]);
for (int q = k; q >= 0; q--)
{
for (int w = 0; w <= q; w++)
{
maxi(dp[gen][q + 2][0], dp[li[gen][a]][w][0]+dp[gen][q-w][0]);
maxi(dp[gen][q + 2][1], dp[li[gen][a]][w][0] + dp[gen][q - w][1]);
maxi(dp[gen][q + 1][1], dp[li[gen][a]][w][1] + dp[gen][q - w][0]);
}
}
}
}
}
int main()
{
while (cin >> n >> k)
{
memset(dp, 0, sizeof(dp));
memset(zhi, 0, sizeof(zhi));
memset(biaoji, 0, sizeof(biaoji));
for (int a = 1; a <= n; a++)
{
li[a].clear();
cin >> zhi[a];
}
int q, w;
for (int a = 1; a <= n - 1; a++)
{
cin >> q >> w;
li[q].push_back(w);
li[w].push_back(q);
}
for (int a = 1; a <= n; a++)
for (int b = 0; b <= k; b++)
dp[a][b][0] = dp[a][b][1] = zhi[a];
dfs(1);
cout << max(dp[1][k][1], dp[1][k][0]) << endl;
}
return 0;
}