POJ 2486 Apple Tree [树状DP]

题目:一棵树,每个结点上都有一些苹果,且相邻两个结点间的距离为1。一个人从根节点(编号为1)开始走,一共可以走k步,问最多可以吃多少苹果。

思路:这里给出数组的定义:

dp[0][x][j] 为从结点x开始走,一共走j步,且j步之后又回到x点时最多能吃到的苹果数。

dp[1][x][j] 为从结点x开始走,一共走j步最多能吃到的苹果数(不必再回到x点)。之所以要定义上面的一种状态是因为在求第二种状态时需要用到。

下面介绍递推公式。

对于结点x,假设它目前要访问的孩子为y,则1...(y-1)已经遍历过。此时有:

dp[0][x][j+2] = max(dp[0][x][j], dp[0][x][m] + dp[0][y][j-m])

注:dp[0][x][m]在每次dp后都会进行更新,此时的dp[0][x][m]实际上只是遍历过孩子结点1...(y-1)的情况。等号左边j之所以要加2是因为右面的总距离没有考虑从点x到y以及从y再回到x的距离,在这里要加上。

dp[1][x][j+1] = max(dp[1][x][j+1], dp[0][x][m] + dp[1][y][j-m])

注:遍历y结点,且不再回来。j加1表示只需要走一次从x到y的边。

dp[1][x][j+2] = max(dp[1][x][j+2], dp[1][x][m] + dp[0][y][j-m])

注:遍历y结点且又回到结点x,则必然是从1...(y-1)中的某个结点有去无回。

另外在dp的过程中,对于结点x的每个孩子都需要枚举走过的步数。而这个步数的枚举从小到大还是从大到小结果是不一样的。这就要看到前面递推公式里的定义,要求dp[0/1][x][m]存储的是遍历y前面的孩子结点的dp值。因此步数要从大到小枚举,这样每次值更新后都不会影响到下次dp。不然会wa。当然,也可以在每次dp前将dp[0/1][x][m]这两个值存储起来,这样就不用考虑这个问题了。

 #include<stdio.h>
#include<string.h>
#include<algorithm>
#define maxn 105
#define maxk 205
using namespace std;
int n, k;
int w[maxn];
bool vis[maxn];
struct node
{
int v, next;
}edge[maxn<<];
int num_edge, head[maxn];
void init_edge()
{
num_edge = ;
memset(head, -, sizeof(head));
}
void addedge(int a,int b)
{
edge[num_edge].v = b;
edge[num_edge].next = head[a];
head[a] = num_edge++;
}
int dp[][maxn][maxk];
void getdp(int x)
{
vis[x] = ;
for (int i = ; i <= k; i++)
dp[][x][i] = dp[][x][i] = w[x];
for (int i = head[x]; i != -; i = edge[i].next)
{
int v = edge[i].v;
if (vis[v]) continue;
getdp(v);
for (int j = k; j >= ; j--)
for (int m = ; m <= j; m++)
{
dp[][x][j+] = max(dp[][x][j+], dp[][x][m] + dp[][v][j-m]);
dp[][x][j+] = max(dp[][x][j+], dp[][x][m] + dp[][v][j-m]);
dp[][x][j+] = max(dp[][x][j+], dp[][x][m] + dp[][v][j-m]);
}
}
}
int main()
{
while (~scanf("%d%d",&n,&k))
{
init_edge();
memset(vis, , sizeof(vis));
for (int i = ; i <= n; i++)
scanf("%d",&w[i]);
for (int i = ; i < n; i++)
{
int a, b;
scanf("%d%d",&a,&b);
addedge(a, b);
addedge(b, a);
}
getdp();
printf("%d\n", dp[][][k]);
}
return ;
}
上一篇:Codeforces 161D Distance in Tree(树型DP)


下一篇:D. Distance in Tree(树型Dp计数)