您的位置:首页 > 移动开发

POJ-2486 Apple Tree 树形DP

2013-01-17 22:55 375 查看
这题和POJ1947类似, 同样是树形DP, 就是因为按照上题的思路写, 导致写的是非常的蛋疼. 调了几小时还是无果. 时候证明还是对状态的意义理解的不透彻.

设dp[x][0][j]表示以节点x为根至多走j步并且返回x处所能够得到的最多苹果.
dp[x][1][j]表示以节点x为根至多走j步不需要返回x处所能够得到的最多苹果.

那么就可以得到动态转移方程(此时的dp[x][..][j]还没有完善, 需要后期处理一下):

dp[x][0][j] = max( dp'[x][0][j-m] + dp[v][0][m] ); 0<=m<=j 其中dp'表示计算到上一个孩子节点为止, v是x的孩子节点
dp[x][1][j] = max( dp'[x][1][j-m] + dp[v][0][m], dp'[x][0][j-m] + dp[v][1][m] ) 0<=m<=j

此时的dp[x][..][j] 并没有计算本身这个节点的权值, 并且进入这个节点同样有距离开销, 因此程序在实现的时候有一个平移更新状态的过程.

代码如下:

#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <iostream>
using namespace std;

/*
题意:给定一棵长满苹果的树, 告诉我们每个节点上有多少个苹果, 现在某人从1这个节点出
发, 最多走K步的情况下, 最多能够得到多少苹果.

解法:
*/

struct Node {
int v, next;
}e[105];

int N, S, G[105][105], apple[105], vis[105];
int head[105], idx, ch[105], dp[105][2][205];

void insert(int a, int b) {
++idx;
e[idx].v = b, e[idx].next = head[a];
head[a] = idx;
}

void visit(int x) {
vis[x] = 1;
for (int i = 1; i <= N; ++i) {
if (!vis[i] && G[x][i]) {
insert(x, i);
++ch[x];
visit(i);
}
}
}

void dfs(int x) {
if (head[x] == -1) { // 如果该点位叶子节点
return;
}
int temp[2][205] = {0}, v;
for (int i = head[x]; i != -1; i = e[i].next) {
dfs(v = e[i].v);
for (int j = S; j >= 2; j--) {
dp[v][0][j] = dp[v][0][j-2]+ apple[v];
}
dp[v][0][1] = dp[v][0][0] = dp[v][1][0] = 0;
for (int j = S; j >= 1; j--) {
dp[v][1][j] = dp[v][1][j-1]+ apple[v];
}
for (int j = 0; j <= S; ++j) {
for (int m = 0; m <= j; ++m) {
temp[0][j] = max(temp[0][j], dp[x][0][j-m] + dp[v][0][m]);
temp[1][j] = max(temp[1][j], dp[x][0][j-m] + dp[v][1][m]);
temp[1][j] = max(temp[1][j], dp[x][1][j-m] + dp[v][0][m]);
}
}
memcpy(dp[x], temp, sizeof (temp));
}
}

int main() {
int x, y;
while (scanf("%d %d", &N, &S) == 2) {
idx = -1;
memset(dp, 0, sizeof (dp));
memset(head, 0xff, sizeof (head));
memset(G, 0, sizeof (G));
memset(ch, 0, sizeof (ch));
memset(vis, 0, sizeof (vis));
for (int i = 1;  i<= N; ++i) {
scanf("%d", apple+i);
}
for (int i = 1; i < N; ++i) {
scanf("%d %d", &x, &y);
G[x][y] = G[y][x] = 1;
}
visit(1); // 建立一棵从1为根的有根树
dfs(1);
printf("%d\n", dp[1][1][S] + apple[1]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: