• BZOJ1017 魔兽地图DotR (树上背包)


    一道背包的神题,用到了树上dp和背包dp,这个题的特殊性在于儿子对于父亲节点是有影响的,所以用f[i][j][k]表示第i号装备,其中用j个来合成上层装备,花费k元所能获得最大的力量值。

    然后对于每一个节点枚举我选择合成几个,遍历每一个儿子节点,背包dp一下花费k元的最大力量值。注意这里的背包是一个分组背包,即对于每一个节点,我需要选择它的每一个叶子节点,这里每一个叶子都是一组物品(因为我需要枚举给每个叶子的花费),我需要选择每一组里的一个物品,所以是一个分组背包,最后用算出背包的g数组去更新f数组,同样是枚举话多少钱,把几个物品用于上层合成,然后转移状态。

    ——by VANE

    #include<bits/stdc++.h>
    using namespace std;
    const int inf=1e9;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-f;ch=getchar();}
        while(ch>='0'&&ch<='9') {x=x*10-'0'+ch;ch=getchar();}
        return f*x;
    }
    int n,m,ans,TOT,cnt;
    int P[55],L[55],M[55];
    int f[55][105][2005];
    int g[2005],h[2005];
    char ch[5];
    int last[55],deg[55];
    struct date{int to,next,v;}e[20005];
    void insert(int u,int v,int w)
    {
        e[++cnt].to=v;e[cnt].next=last[u];
        last[u]=cnt;e[cnt].v=w;deg[v]++;
    }
    void dp(int x)
    {
        if(!last[x])
        {
            L[x]=min(L[x],m/M[x]);
            for(int i=0;i<=L[x];++i)
                for(int j=i;j<=L[x];++j)
                    f[x][i][j*M[x]]=(j-i)*P[x];
            return;
        }
        L[x]=inf;
        for(int i=last[x];i;i=e[i].next)
        {
            dp(e[i].to);
            L[x]=min(L[x],L[e[i].to]/e[i].v);
            M[x]+=e[i].v*M[e[i].to];
        }
        L[x]=min(L[x],m/M[x]);
        
        for(int l=L[x];l>=0;--l)
        {
            memset(g,-0x3f3f3f3f,sizeof g);g[0]=0;
            for(int i=last[x];i;i=e[i].next)
            {
                for(int j=m;j>=0;--j)
                {
                    int t=-1e9;
                    for(int k=0;k<=j;++k)
                        t=max(t,g[j-k]+f[e[i].to][l*e[i].v][k]);
                    g[j]=t;
                }
                    
            }
            for(int j=0;j<=l;++j)
                for(int k=0;k<=m;++k)
                    f[x][j][k]=max(f[x][j][k],g[k]+P[x]*(l-j));
        }
    }
    int main()
    {
        memset(f,-0x3f3f3f3f,sizeof f);
        n=read();m=read();
        for(int i=1;i<=n;++i)
        {
            P[i]=read();
            scanf("%s",ch);
            if(ch[0]=='A')
            {
                int x=read();
                while(x--)
                {
                    int v=read(),num=read();
                    insert(i,v,num);
                }
            }
            else M[i]=read(),L[i]=read();
        }
        for(int x=1;x<=n;++x)
        if(!deg[x])
        {
            dp(x);
            for(int i=m;i>=0;--i)
                for(int j=0;j<=i;++j)
                    h[i]=max(h[i],h[j]+f[x][0][i-j]);
        }
        cout<<h[m];
    }
  • 相关阅读:
    SpringBoot-Shiro普通登录与MD5加密
    uniapp H5 微信浏览器右上角分享
    uniapp ios下 输入密码 中文输入法,无法获取到内容
    uniapp跳转支付宝支付
    uniapp中使用webp格式图片
    uniapp隐藏HTML5+RUNtime
    PC微信多开
    下载blob:https://的视频
    Python字符串转字典
    随机名字生成器
  • 原文地址:https://www.cnblogs.com/nbwzyzngyl/p/8287860.html
Copyright © 2020-2023  润新知