有依赖的背包问题

10. 有依赖的背包问题 - AcWing题库

考虑树形 DP

假设我们对于 u,已经计算完毕子节点 v,那么我们应该如何合并方案呢?

有一种方式是指数级枚举子节点的所有选择方案,但是肯定不可行。

回忆一般背包的状态表示,我们可以直接搬过来用:令 f[u,j] 表示 u 为根的子树内,共 j 体积能产生的贡献。

由于以 u 为根的子树内 u 必须选择,可以先减去 v[u],做一遍 DP,然后最后增加回来即可。

对于每棵子树相互独立,且每棵子树只能选择 f[v][0mv[u]],这就是一个分组背包问题了。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define Ed for(int i=h[x];~i;i=ne[i])
#define Ls(i,l,r) for(int i=l;i<r;++i)
#define Rs(i,l,r) for(int i=l;i>r;--i)
#define Le(i,l,r) for(int i=l;i<=r;++i)
#define Re(i,l,r) for(int i=l;i>=r;--i)
#define L(i,l) for(int i=0;i<l;++i)
#define E(i,l) for(int i=1;i<=l;++i)
#define W(t) while(t--)
#define Wh while

const int N=310,M=N;
int n,m;
int h[N],e[M],ne[M],idx,v[N],w[N],f[N][N],tmp[N];//don't forget memset h!
void add(int a,int b){
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void dfs(int x,int fa){
    int mm=m-v[x],val=w[x];
    Ed{
        int v=e[i];
        if(v==fa)continue;
        dfs(v,x);
        Re(j, mm, 0)
            E(k, j)f[x][j]=max(f[x][j],f[x][j-k]+f[v][k]);
    }
    Re(j, m, v[x])f[x][j]=f[x][j-v[x]]+val;
    L(j, v[x])f[x][j]=0;
}
int main(){
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    #endif
    scanf("%d%d",&n,&m);
    memset(h,-1,n*4+4);
    int rt;
    E(i, n){
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        ~c?add(c,i),0:rt=i;
        v[i]=a,w[i]=b;
    }
    dfs(rt,-1);
    printf("%d",f[rt][m]);
    return 0;
}
posted @   wscqwq  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示