AcWing 10. 有依赖的背包问题(体积枚举理解)
原题链接
困难
作者:
tom233
,
2021-04-15 11:03:38
,
所有人可见
,
阅读 344
#include<iostream>
#include<cstring>
using namespace std;
const int N = 110;
int h[N], e[N], ne[N], idx;
int n, m;
int f[N][N], w[N], v[N];
void add(int a, int b){
e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}
void dfs(int u){
for(int i = h[u]; ~i; i = ne[i]){//遍历组
int son = e[i];
dfs(son);
for(int j = m - v[u]; j >= 0; j -- ){//遍历总体积
for(int k = 0; k <= j; k ++ )//遍历当前组(当前子树)选什么体积
f[u][j] = max(f[u][j], f[u][j - k] + f[son][k]);
//f[u][j - k]意思为在当前子树左边的子树在j-k的体积下的最大值
//所以说j从大到小遍历是因为这样状态转移中的f[u][j - k]才是通过当前子树左边的子树转移过来的
//若从小到大就会覆盖掉前面(和01背包优化成一维类似),就是三维变成了二维
}
}
for(int i = m; i >= v[u]; i -- )f[u][i] = f[u][i - v[u]] + w[u];
for(int i = 0; i < v[u]; i ++ )f[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;
add(p, i);
if(p == -1)root = i;
}
dfs(root);
cout << f[root][m] << endl;
return 0;
}