• HDOJ 1561 The more, The Better(树形DP)


    思路:

    有依赖的背包、泛化背包的思想,和“金明的预算方案”那题是一样的。

    dp[u][i] 表示 u 为根节点的子树,要攻击 i 个城堡所获得的最大金钱数目。其中 u 城堡是已经攻下来的。

    则 dp[u][i] = max(dp[u][i], dp[v][i-1] + val[v]);

    题目中设置出发点位 0,这样的话就可以把森林变成一个棵树,方便于解题。

    解一:采用了泛化物品的并的 O(n * V) 优化解法,15ms

    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int MAXN = 210;
    
    struct edge {
        int v, c;
        edge* next;
    } *V[MAXN], ES[MAXN * 2];
    
    int EC, dp[MAXN][MAXN], val[MAXN];
    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 u = 1; u <= n; ++u)
        {
            int v;
            scanf("%d %d", &v, &val[u]);
            addedge(v, u);
        }
    }
    
    void treedp(int u, int vol)
    {
        vis[u] = true;
    
        for (edge* e = V[u]; e; e = e->next)
        {
            if (vis[e->v])
                continue;
    
            for (int i = vol; i >= 0; --i)
                dp[e->v][i] = dp[u][i];
    
            treedp(e->v, vol - 1);
    
            for (int i = vol; i >= 1; --i)
                dp[u][i] = max(dp[u][i], dp[e->v][i-1] + val[e->v]);
        }
    }
    
    int main()
    {
        int n, m;
        while (scanf("%d %d", &n, &m) && n && m)
        {
            initdata(n);
            memset(dp[0], 0, sizeof(dp[0]));
            treedp(0, m);
            printf("%d\n", dp[0][m]);
        }
        return 0;
    }

    解法二:普通解法 O(n * V * V)

    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int MAXN = 210;
    
    struct edge {
        int v, c;
        edge* next;
    } *V[MAXN], ES[MAXN * 2];
    
    int EC, dp[MAXN][MAXN], val[MAXN];
    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 u = 1; u <= n; ++u)
        {
            int v;
            scanf("%d %d", &v, &val[u]);
            addedge(v, u);
        }
        memset(dp, 0, sizeof(dp));
    }
    
    void treedp(int u, int vol)
    {
        vis[u] = true;
    
        for (edge* e = V[u]; e; e = e->next)
        {
            if (vis[e->v])
                continue;
    
            treedp(e->v, vol - 1);
    
            for (int i = vol; i >= 1; --i)
                for (int j = 1; j <= i; ++j)
                    dp[u][i] = max(dp[u][i], dp[u][j-1] + dp[e->v][i-j] + val[e->v]);
        }
    }
    
    int main()
    {
        int n, m;
        while (scanf("%d %d", &n, &m) && n && m)
        {
            initdata(n);
            treedp(0, m);
            printf("%d\n", dp[0][m]);
        }
        return 0;
    }
     
  • 相关阅读:
    Moonlight Shadow
    读《请尊重我的父亲大人》
    ctrl+alt+F1 开机之后直接进入终端怎么才能返回图形界面?
    MJJCN电台:我有一个梦想
    first time I use a portabledisk to boot the instal
    LoadRunner压力测试结果分析探讨
    测试用例正交分析法
    LoadRunner脚本编写之二
    Centos6.3(64位)下安装Oracle11gR2(64)服务器
    【网站性能指南】
  • 原文地址:https://www.cnblogs.com/kedebug/p/2921493.html
Copyright © 2020-2023  润新知