有依赖的背包问题

原题链接

可以看成对每一棵树u做分组背包,枚举当前树的体积和分配给其子树的体积,由于u是根节点是必选的,所以当前树的体积从m-v[u]开始枚举,相当于0~m-v[u]个物品组,对于子树相当于每个物品组里的物品数量,枚举k为分配给子树的体积
所以状态转移方程为:
f[u][j] = max(f[u][j], f[u][j-k] + f[son][k])

#include <iostream>
#include <algorithm>
#include <cstring>

const int N =  105;

int n, m;
int v[N], w[N];
int f[N][N];
int h[N], e[N], ne[N], idx;

void insert(int a, int b) {
    e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}

void dfs(int u) {
    // 以u为根节点,u必选,体积大于等于v[u]的状态初始化为w[u]
    for (int j = v[u]; j <= m; j ++ ) f[u][j] = w[u];
    for (int i = h[u]; ~i; i = ne[i]) {
        int son = e[i];
        dfs(son);
        // 枚举以u为根节点的树的体积
        for  (int j = m; j >= v[u]; j -- )
            // 枚举分配给子树的体积
            for (int k = 0; k <= j - v[u]; k ++ )
                f[u][j] = std::max(f[u][j], f[u][j - k] + f[son][k]);
    }
}

int main() {
    std::cin >> n >> m;
    memset(h, -1, sizeof h);

    int root = -1;
    for (int i = 1; i <= n; i ++ ) {
        int p;
        std::cin >> v[i] >> w[i] >> p;
        if (p == -1) root = i;
        else insert(p, i);
    }

    dfs(root);

    std::cout << f[root][m] << '\n';
    return 0;
}
posted @   zjh-zjh  阅读(33)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示