zoukankan      html  css  js  c++  java
  • HDOJ 1011 Starship Troopers(树形DP)

    题意:

    给出一棵树,每个点有权值,要取得这个权值需要代价,通过父亲后才能到达儿子。问能量有限时获得的最大值

    思路:

    1. 树形DP,要特殊考虑 m = 0 的情况,

    2. 注意你走过的所有叶子节点都必须留下一人,但是中间的节点可以不留人,即使叶子bugs为0.但是因为要收割possible,必须有 trooper

    3. 用泛化背包优化了半天,无奈水平有限,一直WA,后来想想可能此题确实无法像论文中那样的有依赖背包的优化,因为 m = 0 这个奇葩的存在。

     调试半天虽然优化无果,但是也进一步加深了对于树形动态规划的理解,一些边边角角还是有待于打磨。

    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int MAXN = 110;
    
    struct edge {
        int v;
        edge* next;
    } *V[MAXN], ES[MAXN * 2];
    
    int EC, dp[MAXN][MAXN], B[MAXN], P[MAXN];
    
    void addedge(int u, int v)
    {
        ES[++EC].next = V[u];
        V[u] = ES + EC; V[u]->v = v;
    }
    
    void initdata(int n)
    {
        for (int i = 1; i <= n; ++i)
        {
            scanf("%d %d", &B[i], &P[i]);
            B[i] = (B[i] + 19) / 20;
        }
    
        EC = 0;
        memset(V, 0, sizeof(V));
    
        for (int i = 1; i < n; ++i)
        {
            int a, b;
            scanf("%d %d", &a, &b);
            addedge(a, b);
            addedge(b, a);
        }
        memset(dp, 0, sizeof(dp));
    }
    
    void treedp(int u, int f, int vol)
    {
        if (vol <= 0)
            return ;
    
        dp[u][B[u]] = P[u];
    
        for (edge* e = V[u]; e; e = e->next)
        {
            if (e->v == f)
                continue;
    
            treedp(e->v, u, vol - B[u]);
    
            for (int i = vol; i >= B[u]; --i)
                for (int j = 0; j <= i - B[u]; ++j)
                    dp[u][i] = max(dp[u][i], dp[u][i-j] + dp[e->v][j]);
        }
    
        if (dp[u][0] > 0)
        {
            dp[u][1] = max(dp[u][0], dp[u][1]);
            dp[u][0] = 0;
        }
    }
    
    int main()
    {
        int n, m;
        while (scanf("%d %d", &n, &m))
        {
            if (n == -1 && m == -1)
                break ;
    
            initdata(n);
            treedp(1, 0, m);
    
            printf("%d\n", dp[1][m]);
        }
        return 0;
    }
  • 相关阅读:
    GDB+QEMU调试内核模块(实践篇)
    排序算法的python实现
    Linux命令行相关
    操作系统与网络
    计算机组成原理
    有了自己的技术博客
    if 和 if else
    十效率换算成十六进制
    <<左移 >>右移 >>>无符号右移 &与运算 |或运算 ^异或运算 ~反码
    // &与 // |或 // ^异或 // !非 // &&短路 // ||短路
  • 原文地址:https://www.cnblogs.com/kedebug/p/2921082.html
Copyright © 2011-2022 走看看