问题描述:
解法:
这种树形的结构我们首先很容易去想到 树形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