• BZOJ 1017 魔兽地图


    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

    HINT

     

    Source

    很明显的树形dp。开始我不会d,所以准备照着hzwer的copy,后来弄懂了树p的真谛,天黑都不怕了。

    树p一般都要开dp两次,通过第一个dp结果来dp第二个,再根据第二个来更新第一个(等于第二个dp只是个桥梁吧)。

    像这一题,f[i][j][k]表示i物品贡献给父亲j个花了k的最大力量,通过g数组来完成转移。g[i][k]表示考虑前i个儿子,花j的最大费用,单其实只要一维就够了,因为它可以滚动使用。

    如果实在是听不的话,看代码就行了。我就是看代码才理解的。

      1 #include<iostream>
      2 #include<cstring>
      3 #include<vector>
      4 #include<cstdio>
      5 #include<algorithm>
      6 #include<cstdlib>
      7 using namespace std;
      8 
      9 #define inf (1<<29)
     10 #define maxn 60
     11 #define maxm 2010
     12 #define maxl 110
     13 int n,m,con[maxn],pri[maxn],lim[maxn];
     14 int f[maxn][maxl][maxm],g[maxm],root,ans;
     15 bool bas[maxn];
     16 vector < pair <int,int> > need[maxn];
     17 
     18 inline int Max(int a,int b) { if (a > b) return a; return b; }
     19 
     20 inline int Min(int a,int b) { if (a < b) return a; return b; }
     21 
     22 inline int getint()
     23 {
     24     int x=0,f=1;char ch=getchar();
     25     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     26     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
     27     return x*f;
     28 }
     29 
     30 inline void read()
     31 {
     32     for (int i = 1;i <= n;++i)
     33     {
     34         con[i] = getint();
     35         char opt = getchar();
     36         if (opt == 'A')
     37         {
     38             int nn = getint();
     39             for (int j = 1;j <= nn;++j)
     40             {
     41                 int a = getint(),b = getint();
     42                 need[i].push_back(make_pair(a,b)); 
     43                 bas[a] = true;
     44             }
     45             lim[i] = inf;
     46         }
     47         else pri[i] = getint(),lim[i] = getint();
     48     }
     49     for (int i = 1;i <= n;++i)
     50         if (!bas[i]) { root = i; break; }
     51 }
     52 
     53 inline void dp(int now)
     54 {
     55     if (need[now].size() == 0)
     56     {
     57         lim[now] = Min(lim[now],m/pri[now]);
     58         for (int i = 0;i <= lim[now];++i)
     59             for (int j = i;j <= lim[now];++j)
     60                 f[now][i][j*pri[now]] = (j-i)*con[now];
     61         return;
     62     }
     63     lim[now] = inf; int nn = need[now].size();
     64     for (int i = 0;i < nn;++i)
     65         dp(need[now][i].first),lim[now] = Min(lim[now],lim[need[now][i].first]/need[now][i].second);
     66     for (int i = 0;i <= lim[now];++i) f[now][i][0] = 0;
     67     for (int i = 0;i < nn;++i)
     68         for (int j = 0;j <= lim[now];++j)
     69         {
     70             memcpy(g,f[now][j],sizeof(g));
     71             memset(f[now][j],-1,sizeof(g));
     72             for (int k = m;k >= 0;--k)
     73             {
     74                 for (int r = k;r >= 0; --r)
     75                     if (g[k - r] != -1&&f[need[now][i].first][j*need[now][i].second][r] != -1)
     76                     {
     77                         f[now][j][k] = Max(f[now][j][k],g[k-r]+f[need[now][i].first][j*need[now][i].second][r]);
     78                         ans = Max(ans,f[now][j][k]);
     79                     }
     80             }
     81         }
     82     for (int i = 0;i <= lim[now];++i)
     83         for (int j = i;j <= lim[now];++j)
     84             for (int k = 0;k <= m;++k)
     85             {
     86                 if (f[now][j][k] == -1) continue;
     87                 f[now][i][k] = Max(f[now][i][k],f[now][j][k] + (j-i)*con[now]),ans = Max(ans,f[now][i][k]);
     88             }
     89 }
     90 
     91 int main()
     92 {
     93     freopen("1017.in","r",stdin);
     94     freopen("1017.out","w",stdout);
     95     memset(f,-1,sizeof(f));
     96     scanf("%d %d",&n,&m);
     97     read();
     98     dp(root);
     99     printf("%d",ans);
    100     fclose(stdin); fclose(stdout);
    101     return 0;
    102 }
    View Code
  • 相关阅读:
    大学总结(一)
    关于数组名与指针的相互转换
    错误:无法执行操作,因为未将指定的 Storyboard 应用到此交互控件的对象
    延迟初始化 (Lazy Initialization)
    Sql Server 中 GAM、SGAM、PAM、IAM、DCM 和 BCM 的详解与区别
    Xml格式的字符串(string)到DataSet(DataTable)的转换
    Sql Server 内存用不上的解决办法
    Sql Server 管理区分配(GAM,SGAM)和可用空间(PAM)的原理
    Sql Server LightWeight Pooling(纤程) 选项
    在线 Sql Server 服务无法启动的解决办法
  • 原文地址:https://www.cnblogs.com/mmlz/p/4266214.html
Copyright © 2020-2023  润新知