• 有依赖的背包


    问题描述:

    解法:

    这种树形的结构我们首先很容易去想到 树形dp ,但是和 树形dp 不一样的地方在于它选一个节点的话还有附加条件(也就是依赖关系)

    我们对于每一个节点可以把它看成一个分组背包

    dp[i][j] 代表 选第 i 个节点 背包容量为 j 的时候 背包的最大价值

    我们可以先采取 树形dp 的方法去更新叶子节点,然后更新父亲节点

    更新父亲节点的状态转移方程也很好想:

    dp[i][j] = max(dp[i][j],dp[son][k]+dp[i][j-k])

    int n,m;
    int h[110],e[110],next[110],cnt;
    int v[110],w[110],dp[110][110];
    
    void add(int a,int b) {
        e[cnt] = b;
        next[cnt] = h[a];
        h[a] = cnt++;
    }
    
    void dfs(int u) {
        for (int i = h[u];i != -1;i = next[i]) {
            int son = e[i];
            dfs(son);
            for (int j = m-v[u];j >= 0;j--) {  // 因为必须如果选了孩子必须选父亲,先把父亲的位置空出来
                for (int k = 0;k <= j;k++) {
                    dp[u][j] = std::max(dp[u][j],dp[u][j-k]+dp[son][k]);
                }
            }
        }
        // 更新叶子
        for (int i = m;i >= v[u];i--)
            dp[u][i] = dp[u][i-v[u]] + w[u];
        for (int i = 0;i < v[u];i++)
            dp[u][i] = 0;
    }
    
    int main() {
        memset(h,-1, sizeof(h));
        cin >> n >> m;
        int root;
        for (int i = 1;i <= n;i++) {
            int p;
            cin >> v[i] >> w[i] >> p;
            if (p == -1)
                root = i;
            else
                add(p,i);
        }
        dfs(root);
        cout << dp[root][m] << endl;
        return 0;
    }
  • 相关阅读:
    [不知道哪来的题] Subsequence
    [不知道哪来的题] 变量(variable)
    [不知道哪来的题] 串(string)
    LOJ#500. 「LibreOJ β Round」ZQC 的拼图
    Codeforces855C Helga Hufflepuff's Cup
    Codeforces895C Square Subsets
    Codeforces757D Felicity's Big Secret Revealed
    bzoj3694 最短路
    maven安装时报错的问题
    java static关键字
  • 原文地址:https://www.cnblogs.com/-Ackerman/p/12252668.html
Copyright © 2020-2023  润新知