• [BZOJ1017][JSOI2008]魔兽地图DotR 树形dp


    1017: [JSOI2008]魔兽地图DotR

    Time Limit: 30 Sec  Memory Limit: 162 MB
    Submit: 2597  Solved: 1010
    [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

    对于这道题,我们设f[i][j][k]表示处理到第i个点,向父亲节点合并j个装备,花了k元钱的最大力量值(不包括合并的j个)。

    设g[i][j]表示当前节点的前i个子树花了j元钱的最大力量(不包括合并的)。

    我们先枚举购买当前装备的总数量b,

    对于f的转移,我们枚举j,k,有转移方程f[i][j][k]=max{g[i][k]+p[i]*(b-j)}

    对于g的转移,我们枚举子树tot,钱数j和当前子树的钱数k,有g[tot][j]=max{g[tot-1][j-k]+f[i][b*e[i].v][k]}

    之后统计答案即可

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<cstdlib>
     5 #include<cmath>
     6 #include<algorithm>
     7 using namespace std;
     8 int read() {
     9     int x=0,f=1;char ch=getchar();
    10     while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
    11     while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
    12     return x*f;
    13 }
    14 int n,m,cnt,tot,ans;
    15 int p[55],L[55],M[55];
    16 int f[55][105][2005];
    17 int g[55][2005],h[55][2005];
    18 char ch[5];
    19 int head[55],deg[55];
    20 struct data{int to,next,v;}e[20005];
    21 void add(int u,int v,int w){e[cnt].to=v;e[cnt].next=head[u];head[u]=cnt;e[cnt].v=w;cnt++;deg[v]++;}
    22 void dfs(int now) {
    23     if(head[now]<0) {
    24         L[now]=min(L[now],m/M[now]);
    25         for(int i=0;i<=L[now];i++)
    26             for(int j=i;j<=L[now];j++) f[now][i][j*M[now]]=(j-i)*p[now];
    27         return ;
    28     }
    29     L[now]=214748364;
    30     for(int i=head[now];i>=0;i=e[i].next) {
    31         int to=e[i].to;
    32         dfs(to);
    33         L[now]=min(L[now],L[to]/e[i].v);
    34         M[now]+=e[i].v*M[to];
    35     }
    36     L[now]=min(L[now],m/M[now]);
    37     memset(g,-47,sizeof(g));
    38     g[0][0]=0;
    39     for(int b=L[now];b>=0;b--) {
    40         int tot=0;
    41         for(int i=head[now];i>=0;i=e[i].next) {
    42             tot++;
    43             for(int j=0;j<=m;j++)
    44                 for(int k=0;k<=j;k++){
    45                     g[tot][j]=max(g[tot][j],g[tot-1][j-k]+f[e[i].to][b*e[i].v][k]);}
    46         }
    47         for(int i=0;i<=b;i++)
    48             for(int j=0;j<=m;j++)
    49                 f[now][i][j]=max(f[now][i][j],g[tot][j]+p[now]*(b-i));
    50     }
    51 }
    52 int main() {
    53     memset(head,-1,sizeof(head));
    54     memset(f,-47,sizeof(f));
    55     n=read(),m=read();
    56     for(int i=1;i<=n;i++) {
    57         p[i]=read();
    58         scanf("%s",ch);
    59         if(ch[0]=='A') {
    60             int x=read();
    61             while(x--) {
    62                 int v=read(),num=read();
    63                 add(i,v,num);
    64             }
    65         }
    66         else M[i]=read(),L[i]=read();
    67     }
    68     int sum=0;
    69     for(int x=1;x<=n;x++) {
    70         if(!deg[x]) {
    71             dfs(x);
    72             sum++;
    73             for(int i=0;i<=m;i++)
    74                 for(int j=0;j<=i;j++)
    75                     for(int k=0;k<=L[x];k++)
    76                         h[sum][i]=max(h[sum][i],h[sum-1][j]+f[x][k][i-j]);
    77         }
    78     }
    79     int ans=0;
    80     for(int i=0;i<=m;i++) ans=max(ans,h[sum][i]);
    81     cout<<ans;
    82 }
    View Code
    O(∩_∩)O~ (*^__^*) 嘻嘻…… O(∩_∩)O哈哈~
  • 相关阅读:
    VUE网页loading加载状态
    VUE使用canvas画板实现签字
    一个完整的项目管理流程
    APP原型的设计步骤是什么?
    如何对接网建SMS短信通短信验证码接口
    如何彻底红蜘蛛,非常方便!!!
    如何在cmd中连接数据库
    mvn deploy:deploy-file命令
    Java线程池的分析和使用
    jstat命令详解
  • 原文地址:https://www.cnblogs.com/wls001/p/7647387.html
Copyright © 2020-2023  润新知