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 }
     
     
     
  • 相关阅读:
    文件搜索和图像裁剪
    Mat的复制
    map
    substr
    cin,scanf
    strstr
    Applying vector median filter on RGB image based on matlab
    sobel算子的一些细节
    matlab 有趣小细节
    高斯混合模型(GMM)
  • 原文地址:https://www.cnblogs.com/chty/p/5884796.html
Copyright © 2011-2022 走看看