• 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;
    }
     
  • 相关阅读:
    android的FATAL EXCEPTION: main错误
    ORA12560: TNS: 协议适配器错误
    BroadcastReceiver应用详解
    using C# 详解
    mysqlproxy0.8版本读写分离测试总结
    Mysql SHOW PROCESSLIST Sending data
    [转载]大型网站运维探讨和心得
    找出并optimization表
    mysql中普通索引和唯一索引的效率对比
    ps aux 中STAT 解释
  • 原文地址:https://www.cnblogs.com/kedebug/p/2921493.html
Copyright © 2020-2023  润新知