POJ 2486 apple tree(树形dp)

题意:

一棵树,每个节点有一个权值,求从根节点出发,最多走K步,能够取得的最大权值(可以往回走)。

思路:

dp[1][u][j]  从u节点出发,最多走j步(可以小于j步),并且返回到 u 节点,可以获得的最大权值。

dp[0][u][j] 从u节点出发,最多走j步,最终停留在u的子树节点,可以获得的最大权值。

关键是状态转移方程啊,涉及到停留在 u 点和停留在 v 点展开了优化讨论:

dp[1][u][i+2] = max(dp[1][u][i+2], dp[1][v][i-j] + dp[1][u][j]);
dp[0][u][i+2] = max(dp[0][u][i+2], dp[1][v][i-j] + dp[0][u][j]);
dp[0][u][i+1] = max(dp[0][u][i+1], dp[0][v][i-j] + dp[1][u][j]);

其中v是u节点的孩子节点,j range from K to 0(类似01背包)

代码中使用了一点小小的剪枝:由于没走到一个孩子节点,步数至少减少 1 的,所以可以逐步把步数减 1,最终代码跑到了 32ms.


#include <iostream>
#include <algorithm>
using namespace std;

const int MAXN = 110;
const int MAXD = 210;

structedge {
    int v;
    edge* next;
} *V[MAXN], ES[MAXN * 2];

int EC, N, K, val[MAXN], dp[2][MAXN][MAXD];
bool vis[MAXN];

void addedge(int u, int v)
{
    ES[++EC].next = V[u];
    V[u] = ES + EC; V[u]->v = v;
}

void initdata(int n)
{
    EC = 0;
    memset(V, 0, sizeof(V));
    memset(vis, false, sizeof(vis));

    for (int i = 1; i <= n; ++i)
        scanf("%d", &val[i]);

    for (int i = 1; i <= n - 1; ++i)
    {
        int a, b;
        scanf("%d %d", &a, &b);
        addedge(a, b);
        addedge(b, a);
    }
}

void treedp(int u, int vol)
{
    vis[u] = true;

    for (int j = 0; j <= vol; ++j)
        dp[0][u][j] = dp[1][u][j] = val[u];

    for (edge* e = V[u]; e; e = e->next)
    {
        int v = e->v;
        if (vis[v])
            continue;

        treedp(v, vol - 1);

        for (int i = vol; i >= 0; --i)
        {
            for (int j = 0; j <= i; ++j)
            {
                dp[1][u][i+2] = max(dp[1][u][i+2], dp[1][v][i-j] + dp[1][u][j]);
                dp[0][u][i+2] = max(dp[0][u][i+2], dp[1][v][i-j] + dp[0][u][j]);
                dp[0][u][i+1] = max(dp[0][u][i+1], dp[0][v][i-j] + dp[1][u][j]);
            }
        }
    }
}

int main()
{
    while (scanf("%d %d", &N, &K) != EOF)
    {
        initdata(N);
        treedp(1, K);
        printf("%d\n", dp[0][1][K]);
    }
    return 0;
}
-------------------------------------------------------

kedebug

Department of Computer Science and Engineering,

Shanghai Jiao Tong University

E-mail: kedebug0@gmail.com

GitHub: http://github.com/kedebug

-------------------------------------------------------

原文地址:https://www.cnblogs.com/kedebug/p/2761123.html