zoukankan      html  css  js  c++  java
  • [JSOI2008]魔兽地图(树形dp)

    DotR (Defense of the Robots) Allstars是一个风靡全球的魔兽地图,他的规则简单与同样流行的地图DotA (Defense of the Ancients) Allstars。

    DotR里面的英雄只有一个属性——力量。他们需要购买装备来提升自己的力量值,每件装备都可以使佩戴它的英雄的力量值提高固定的点数,所以英雄的力量值等于它购买的所有装备的力量值之和。装备分为基本装备和高级装备两种。基本装备可以直接从商店里面用金币购买,而高级装备需要用基本装备或者较低级的高级装备来合成,合成不需要附加的金币。装备的合成路线可以用一棵树来表示。

    比如,Sange and Yasha的合成需要Sange,Yasha和Sange and Yasha Recipe Scroll三样物品。其中Sange又要用Ogre Axe, Belt of Giant Strength和 Sange Recipe Scroll合成。每件基本装备都有数量限制,这限制了你不能无限制地合成某些性价比很高的装备。

    现在,英雄Spectre有M个金币,他想用这些钱购买装备使自己的力量值尽量高。你能帮帮他吗?他会教你魔法Haunt(幽灵附体)作为回报的。

    Solution

    极强的一道树形dp题。

    我们设dp[i][j][k]表示当前正在做以i为根的子树,我们需要用j个物品用于向上合成,花费了k元能够获得的最大收益。

    首先我们可以递归回溯求出每个点的价格和他的限制购买次数(这个东西是和儿子节点相关的)。

    然后就枚举向上传多少个物品,在这里我们记录一个辅助数组g[i][j]表示做到了第i棵子树,背包体积为j时能够获得的最大收益。

    但它可能有多个联通块,做完每个子树后我们再把它合并到一个数组里就可以了。

    Code

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define inf 1e9
    #define N 55
    #define M 2010
    using namespace std;
    int dp[N][N<<1][M],g[N][M],head[N],w[N],va[N],l[N],f[N][M],tot,m,n,ji[N];
    struct efr{
        int n,to,l;
    }an[20009];
    inline void add(int u,int v,int l){
        an[++tot].n=head[u];
        an[tot].to=v;
        an[tot].l=l;
        head[u]=tot;
    }
    void dfs(int u){
        if(!head[u]){
            l[u]=min(l[u],m/va[u]);//这里求出这件物品的购买限制 
            for(int i=0;i<=l[u];++i)
               for(int j=i;j<=l[u];++j)
                  dp[u][i][j*va[u]]=(j-i)*w[u];//j 表示买了多少个 
            return;
        }
        l[u]=inf;
        for(int i=head[u];i;i=an[i].n){
            int v=an[i].to;
            dfs(v);
            l[u]=min(l[u],l[v]/an[i].l);//更新l得知 
            va[u]+=va[v]*an[i].l;//在这里递归计算u的价值 
        }
        l[u]=min(l[u],m/va[u]); 
        memset(g,-0x3f,sizeof(g));
        g[0][0]=0;
        for(int o=l[u];o>=0;--o){//枚举上传几个 
            int cnt=0;
            for(int i=head[u];i;i=an[i].n){
             int v=an[i].to;
             cnt++;
            for(int j=m;j>=0;--j)
              for(int k=0;k<=j;++k)
                g[cnt][j]=max(g[cnt][j],g[cnt-1][j-k]+dp[v][o*an[i].l][k]);
            }
            for(int i=0;i<=o;++i)
              for(int j=0;j<=m;++j)
                 dp[u][i][j]=max(dp[u][i][j],g[cnt][j]+w[u]*(o-i)); 
        }
    }
    inline char rd(){
        char c=getchar();
        while(c!='A'&&c!='B')c=getchar();
        return c;
    }
    int main(){
        scanf("%d%d",&n,&m);
        memset(dp,-0x3f,sizeof(dp));
        char c;
        for(int i=1;i<=n;++i){
            scanf("%d",&w[i]);
            c=rd();
            if(c=='B')scanf("%d%d",&va[i],&l[i]);
            else{
                int x,y,z;
                scanf("%d",&x);
                for(int j=1;j<=x;++j){
                   scanf("%d%d",&y,&z);
                   add(i,y,z);
                   ji[y]=1;
                } 
            }
        }
        int cnt=0;
        for(int i=1;i<=n;++i)
          if(!ji[i]){
              dfs(i);
              cnt++;
              for(int j=0;j<=m;++j)
                for(int k=0;k<=j;++k)
                  f[cnt][j]=max(f[cnt][j],f[cnt-1][j-k]+dp[i][0][k]);
          } 
       int ans=0;
       for(int i=0;i<=m;++i)
         ans=max(ans,f[cnt][i]);
       cout<<ans;
        return 0;
    } 
  • 相关阅读:
    java.utils.HashMap数据结构分析(转)
    oracle什么时候须要commit
    CreateFont具体解释
    Java工厂模式
    簡單SQL存儲過程實例
    Cocos2d-x 3.0新引擎文件夹结构
    设计模式之十 适配器模式
    腰围2尺1,2,3,4,5,6,7,8寸各自等于是多少厘米/英寸(对比表)
    iOS 基础函数解析
    内部元素一一相应的集合的算法优化,从list到hashmap
  • 原文地址:https://www.cnblogs.com/ZH-comld/p/9813050.html
Copyright © 2011-2022 走看看