• [bzoj1017] [JSOI2008] 魔兽地图


    题目链接

    树上背包。

    (f[i][j][k])表示(i)节点有(j)个来合成高一级的装备,买(i)节点及其子树的装备共花了不大于(k)元可以得到的最大力量值。

    对于每一颗树做(tree~dp)转移,如果是叶子节点就直接算,

    否则先根据儿子的限制以及钱的限制处理出最多可以买几个,然后枚举当前这件装备做几个,设(g[j])为花(j)元做(i)件当前的装备之后剩下的边角料的最大获利,这个可以枚举儿子之后类似于背包的转移。之后(f)根据(g)算一遍就行了。

    #include<bits/stdc++.h>
    using namespace std;
    inline void read(int &x) {
        int f=1;x=0;char ch=getchar();
        for(;!isdigit(ch);ch=getchar()) if(ch=='-') f-=f;
        for(;isdigit(ch);ch=getchar()) x=(x<<1)+(x<<3)+(ch^48);x*=f;
    }
    inline void print(int x) {
        if(x<0) putchar('-'),x=-x;
        if(!x) return ;
        print(x/10);putchar((x%10)^48);
    }
    inline void write(int x) {if(!x) putchar('0');else print(x);putchar('
    ');}
    int f[60][120][2005],g[2005],n,head[60],tot,m,v[120],c[120],lim[120],vis[120],ans[2001],deg[120];
    struct edge{int to,nxt,w;}e[120];
    void ins(int u,int v,int w) {e[++tot].to=v,e[tot].nxt=head[u],head[u]=tot,e[tot].w=w;}
    void dfs(int x) {
        if(vis[x]) return ;vis[x]=1;
        if(!head[x]) {
            lim[x]=min(lim[x],m/c[x]);
            for(int i=lim[x];~i;i--)
                for(int j=i;j<=lim[x];j++)
                    f[x][i][j*c[x]]=v[x]*(j-i);
            return ;
        }lim[x]=1e9;
        for(int i=head[x];i;i=e[i].nxt) {
            dfs(e[i].to);
            lim[x]=min(lim[x],lim[e[i].to]/e[i].w);
            c[x]+=c[e[i].to]*e[i].w;
        }
        lim[x]=min(lim[x],m/c[x]);
        for(int i=lim[x];~i;i--) {
            memset(g,-0x3f,sizeof g);g[0]=0;
            for(int j=head[x];j;j=e[j].nxt)
                for(int k=m;~k;k--) {
                    int t=-1e9;
                    for(int p=0;p<=k;p++)
                        t=max(t,g[k-p]+f[e[j].to][e[j].w*i][p]);
                    g[k]=t;
                }
            for(int j=0;j<=i;j++)
                for(int k=0;k<=m;k++)
                    f[x][j][k]=max(f[x][j][k],g[k]+(i-j)*v[x]);
        }
    }
    int main() {
        read(n);read(m);memset(f,-0x3f,sizeof f);
        for(int i=1;i<=n;i++) {
            read(v[i]);char ch[2];scanf("%s",ch+1);
            if(ch[1]=='A') {
                int T;read(T);int x,y;
                for(int j=1;j<=T;j++) read(x),read(y),ins(i,x,y),deg[x]++;
            }else read(c[i]),read(lim[i]);
        }
        for(int i=1;i<=n;i++)
            if(!deg[i]) {
                dfs(i);//write(i);
                for(int j=m;~j;j--)
                    for(int k=0;k<=j;k++)
                        ans[j]=max(ans[j],ans[j-k]+f[i][0][k]);
            }
        write(ans[m]);
        return 0;
    }
    
    
  • 相关阅读:
    log日志----logging模块
    配置文件--configparser
    面向对象——进阶
    面向对象
    内置函数
    模块和包
    常用模块
    正则表达式
    递归函数
    内置函数+匿名函数
  • 原文地址:https://www.cnblogs.com/hbyer/p/9832179.html
Copyright © 2020-2023  润新知