有依赖的背包

问题描述:

解法:

这种树形的结构我们首先很容易去想到 树形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;
}

原文地址:https://www.cnblogs.com/-Ackerman/p/12252668.html

时间: 2024-10-08 20:20:28

有依赖的背包的相关文章

C. Coin Troubles 有依赖的背包 + 完全背包变形

http://codeforces.com/problemset/problem/283/C 一开始的时候,看着样例不懂,为什么5 * a1 + a3不行呢?也是17啊 原来是,题目要求硬币数目a3 > a4 > a2,那么,不选的话,是不合法的.就是0.0.0这样是不合法的,因为a3 = a4了. 那么就可以知道, a3起码都要选两个了. 那么怎么维护这个关系呢?,思路是有依赖的背包,需要a3的数目比a4的多,就可以把a4那件物品变成a3 + a4 那么每一次选择的时候,就隐含地选了一件a3

HAOI2010 软件安装 有依赖的背包DP

题目描述 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一 些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大). 但是现在有个问题:软件之间存在依赖关系,即软件i只有在安装了软件j(包括软件j的直接或间接依赖)的情况下才能正确工作(软件i依赖软件j).幸运的 是,一个软件最多依赖另外一个软件.如果一个软件不能正常工作,那么它能够发挥的作用为0. 我们现在知道了软件之间的依赖关系:软件i依赖软件Di.现在请你设计出

树形依赖的背包 树形dp

树形DP有一个独特的优化,就是通过递归,枚举目前有效的元素个数,求dp[ i ][ j ] (表示 选取以i为根的子树中有选取j个元素的最大取值) (搭配 siz 数组表示当前该节点的总共子孙数) 1.hdu1561(树形依赖背包裸题) 注意 siz 数组的运用,以及 u 点选择的节点数时要逆向枚举,就像01背包 复杂度看似O(n^3),实际是 O( n^2 ) 左右. #include <iostream> #include <cstdio> #include <cstri

Consumer (有依赖的背包)

题目大意: 给你一些物品,每个物品有自己的花费和价值,每个物品 都有相对应的箱子, 如果你想要买这个物品,你就需要先买这个箱子(依赖),求 n个箱子花费 t 能获得的最大价值 思路: dp[i][j]  代表在 i 个箱子花费 j 能获得的最大价值 我们需要优先对箱子进行处理,处理完之后其他的都和 01背包一样了 具体的看代码注释吧 int dp[55][100010]; int n,t,box,num; int main () { int i,j,k; while(scanf("%d %d&q

hdu 3449 Consumer (依赖01背包)

题目: 链接:点击打开链接 题意: 思路: dp[i][j]表示前i个箱子装j钱的材料可以得到的最大价值. 代码: #include<iostream> #include<cstdio> #include<cstring> using namespace std; #define MAXN 100010 int dp[55][MAXN]; int main() { //freopen("input.txt","r",stdin);

P1064 金明的预算方案(01背包||有依赖的背包(待解决))

直接01背包硬刚,虽然容易理解,但是完全不适合附件多的情况 1 /* 2 1.只选主件 3 2.选主件和附件1 4 3.选主件和附件2 5 4.选主件和附件1.2 6 */ 7 #include <iostream> 8 #include<string> 9 #include<cstdio> 10 #include<cmath> 11 #define ll long long 12 using namespace std; 13 int V[70][3],P

金明的预算方案————有依赖的背包

题目描述 金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间金明自己专用的很宽敞的房间.更让他高兴的是,妈妈昨天对他说:“你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过N元钱就行”.今天一早,金明就开始做预算了,他把想买的物品分为两类:主件与附件,附件是从属于某个主件的,下表就是一些主件与附件的例子: 主件 附件 电脑 打印机,扫描仪 书柜 图书 书桌 台灯,文具 工作椅 无 如果要买归类为附件的物品,必须先买该附件所属的主件.每个主件可以有0个.1个或2个附件.附件不再有从属于

HDU 1561 ——The more, The Better(有依赖的树形DP)

题目分析: 攻占城堡所能获得的最多宝物,但是有个限制,要想攻占某个城堡前必须先攻占另一个城堡 思路: 建图,新建一个根节点为0,那么题目就变为要想取得子节点必须先取得它的父亲节点 今天为了解决这个问题,看了下背包九讲中的有依赖的背包,刷了道模板题. 大概思路是:要想取得附件必须先取主件,主件要么取,要么不取,取得话要怎么分配给附件,用01背包处理附件,然后再把每个主件分组背包 树形的依赖主要是附件是个集合,附件还有附件.森林的概念 根据DP的思想,我们先dfs到叶,01背包操作 即可.只是每次d

背包DP:金明的预算方案

金明的预算方案 2006年NOIP全国联赛提高组 题目描述 Description 金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间金明自己专用的很宽敞的房间.更让他高兴的是,妈妈昨天对他说:“你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过N元钱就行”.今天一早,金明就开始做预算了,他把想买的物品分为两类:主件与附件,附件是从属于某个主件的,下表就是一些主件与附件的例子: 如果要买归类为附件的物品,必须先买该附件所属的主件.每个主件可以有0个.1个或2个附件.附件不再有从属于自