zoukankan      html  css  js  c++  java
  • 【bzoj1017】[JSOI2008]魔兽地图DotR

    1017: [JSOI2008]魔兽地图DotR

    Time Limit: 30 Sec  Memory Limit: 162 MB
    Submit: 1658  Solved: 755
    [Submit][Status][Discuss]

    Description

      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(幽灵附体)作为回报的。

    Input

      第一行包含两个整数,N (1 <= n <= 51) 和 m (0 <= m <= 2,000)。分别表示装备的种类数和金币数。装备
    用1到N的整数编号。接下来的N行,按照装备1到装备n的顺序,每行描述一种装备。每一行的第一个正整数表示这
    个装备贡献的力量值。接下来的非空字符表示这种装备是基本装备还是高级装备,A表示高级装备,B表示基本装备
    。如果是基本装备,紧接着的两个正整数分别表示它的单价(单位为金币)和数量限制(不超过100)。如果是高
    级装备,后面紧跟着一个正整数C,表示这个高级装备需要C种低级装备。后面的2C个数,依次描述某个低级装备的
    种类和需要的个数。

    Output

      第一行包含一个整数S,表示最多可以提升多少点力量值。

    Sample Input

    10 59
    5 A 3 6 1 9 2 10 1
    1 B 5 3
    1 B 4 3
    1 B 2 3
    8 A 3 2 1 3 1 7 1
    1 B 5 3
    5 B 3 3
    15 A 3 1 1 5 1 4 1
    1 B 3 5
    1 B 4 3

    Sample Output

    33
     
     
    【题解】

    设P[x],L[x],M[x],表示物品x的能量,购买上限与价格

    L[x]=min(L[x],m/M[x])

    高级装备的M和L随便dp一下

    再用f[i][j][k]表示第i个物品,有j件用于上层的合成,花费金钱是k所能获得的最大力量

    对于以x为根的子树,枚举合成 l 个 x 物品,然后再用其余的钱买一些 x 子树内的装备不用于合成

    枚举合成物品数量 l ,用g[i][j]表示x的前i个儿子的子树,花费j的钱,所能获得的最大力量

    g[tot][j]=max{g[tot-1][j-k]+f[e[i].to][l*e[i].v][k]}

    //e[i].to是儿子结点,e[i].v是所需数量,就是从j中拿出k的钱在e[i].to的子树内购买

    最后再枚举合成的 l 个 x 物品中有 j 个是直接用于增加力量,剩余用于合成的

    f[x][j][k]=max{g[tot][k]+P[x]*(l-j)}

    ——转自hzwer
    这是一道树归题,但我没想出做法,看的黄学长的题解。(状态转移很魔性,需要用子节点的状态合并得到父节点)
    蒟蒻碰到神题,只有膜拜。  %%%%%%%%%%%%
     
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cstdlib>
     5 #include<cmath>
     6 #include<ctime>
     7 #include<algorithm>
     8 using namespace std;
     9 #define inf 1000000000
    10 struct node{int y,next,v;}e[20005];
    11 int n,m,len,ans,Link[60],id[60],P[60],L[60],M[60],g[60][2005],f[60][105][2005];
    12 inline int read()
    13 {
    14     int x=0,f=1;  char ch=getchar();
    15     while(!isdigit(ch))  {if(ch=='-')  f=-1;  ch=getchar();}
    16     while(isdigit(ch))  {x=x*10+ch-'0';  ch=getchar();}
    17     return x*f;
    18 }
    19 void insert(int x,int y,int v)
    20 {
    21     e[++len].next=Link[x];
    22     Link[x]=len;
    23     e[len].y=y;
    24     e[len].v=v;
    25     id[y]++;
    26 }
    27 void dp(int x)
    28 {
    29     if(!Link[x])//如果是单独的叶子节点
    30     {
    31         L[x]=min(L[x],m/M[x]);
    32         for(int j=0;j<=L[x];j++)
    33             for(int k=j;k<=L[x];k++)
    34                 f[x][j][k*M[x]]=(k-j)*P[x];
    35         return;
    36     }
    37     L[x]=inf;
    38     for(int i=Link[x];i;i=e[i].next)//从子节点更新高级装备的L和M值
    39     {
    40         dp(e[i].y);
    41         L[x]=min(L[x],L[e[i].y]/e[i].v);
    42         M[x]+=M[e[i].y]*e[i].v;
    43     }
    44     L[x]=min(L[x],m/M[x]);
    45     memset(g,-0x3f3f3f3f,sizeof(g));
    46     g[0][0]=0;
    47     for(int l=L[x];l>=0;l--)
    48     {
    49         int tot=0;
    50         for(int i=Link[x];i;i=e[i].next)//计算g数组
    51         {
    52             tot++;
    53             for(int j=0;j<=m;j++)
    54                 for(int k=0;k<=j;k++)
    55                     g[tot][j]=max(g[tot][j],g[tot-1][j-k]+f[e[i].y][e[i].v*l][k]);
    56         }
    57         for(int j=0;j<=l;j++)//计算f数组
    58             for(int k=0;k<=m;k++)
    59                 f[x][j][k]=max(f[x][j][k],g[tot][k]+P[x]*(l-j));
    60     }
    61 }
    62 int main()
    63 {
    64     //freopen("cin.in","r",stdin);
    65     //freopen("cout.out","w",stdout);
    66     memset(f,-0x3f3f3f3f,sizeof(f));
    67     n=read();  m=read();
    68     for(int i=1;i<=n;i++)
    69     {
    70         P[i]=read();
    71         char ch;  scanf("%c",&ch);
    72         if(ch=='A')
    73         {
    74             int x=read();
    75             while(x--)
    76             {
    77                 int y=read(),v=read();
    78                 insert(i,y,v);//从父亲连向儿子,因为要用子节点更新父节点
    79             }
    80         }
    81         else M[i]=read(),L[i]=read();
    82     }
    83     for(int i=1;i<=n;i++)
    84         if(!id[i])//从根节点开始dp
    85         {
    86             dp(i);
    87             for(int j=0;j<=L[i];j++)
    88                 for(int k=0;k<=m;k++)
    89                     ans=max(ans,f[i][j][k]);
    90         }
    91     printf("%d
    ",ans);
    92     return 0;
    93 }
     
     
     
  • 相关阅读:
    LeetCode 275. H-Index II
    LeetCode 274. H-Index
    LeetCode Gray Code
    LeetCode 260. Single Number III
    LeetCode Word Pattern
    LeetCode Nim Game
    LeetCode 128. Longest Consecutive Sequence
    LeetCode 208. Implement Trie (Prefix Tree)
    LeetCode 130. Surrounded Regions
    LeetCode 200. Number of Islands
  • 原文地址:https://www.cnblogs.com/chty/p/5884796.html
Copyright © 2011-2022 走看看