1017: [JSOI2008]魔兽地图DotR

Time Limit: 30 Sec  Memory Limit: 162 MB
Submit: 2308  Solved: 919
[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
 
//先标明参考来源 http://hzwer.com/5198.html
 
大体上就是好几个子树,然后对子树进行DP的样子,没有建立虚拟根节点,也是用子节点的状态去更新父节点的状态,细节见代码。
 
#include<cstdio>
#include<cstring>
#include<algorithm>
const int inf=1e9;
using namespace std;
int n,m,cnt,tot,ans;
int P[],L[],M[];
int f[][][];
int g[][],h[][];
char ch[];
int last[],deg[];
struct data{int to,next,v;}e[];
void insert(int u,int v,int w) {
    e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt;e[cnt].v=w;
    ++deg[v];
}
void dp(int x) {
    if(!last[x]) {   //倘若这个就是基本装备,那么记录一下其f数组的值就可以直接return了。
        L[x]=min(L[x],m/M[x]);
        for(int i=;i<=L[x];++i)
            for(int j=i;j<=L[x];++j)
            f[x][i][j*M[x]]=(j-i)*P[x];//f[i][j][k],第i个物品,有j件用于上层的合成,花费金钱k所能获得的最大力量
        return;
    }
    L[x]=inf;
    for(int i=last[x];i;i=e[i].next) {  
        dp(e[i].to);  //向下对其子节点进行处理。
        L[x]=min(L[x],L[e[i].to]/e[i].v);  //更新数量
        M[x]+=e[i].v*M[e[i].to];//更新花费
    }
    L[x]=min(L[x],m/M[x]);
    memset(g,-0x3f3f3f3f,sizeof(g));
    g[][]=;//表示x的前i个儿子的子树,花费j的钱,所能获得的最大力量
    for(int l=L[x];l>=;--l) {   //此处开始处理父节点出的f数组值,枚举合成复合装备的数量,***注意for循环的方向是由L[x]到0***。
        int tot=;
        for(int i=last[x];i;i=e[i].next) {
            ++tot;//这一行和上一行就相当于枚举每个基本装备
            for(int j=;j<=m;++j)     //两个for的原因是因为花费不一定全部用完
                for(int k=;k<=j;++k)
                g[tot][j]=max(g[tot][j],g[tot-][j-k]+f[e[i].to][l*e[i].v][k]);
        }
        for(int j=;j<=l;++j)//***此处for循环的方向没有影响***
            for(int k=;k<=m;++k)
            f[x][j][k]=max(f[x][j][k],g[tot][k]+P[x]*(l-j));  //对f进行更新
    }
}
int main(){
    int x;
    memset(f,-0x3f3f3f3f,sizeof(f));
    scanf("%d%d",&n,&m);
    for(int i=;i<=n;++i) {
        scanf("%d%s",&P[i],ch);
        if(ch[]=='A') {
            scanf("%d",&x);
            while(x--) {
                    int v,num;
                scanf("%d%d",&v,&num);
                insert(i,v,num);
            }
        }
        else scanf("%d%d",&M[i],&L[i]);
    }
    for(int x=;x<=n;++x) {
        if(!deg[x]) {
            dp(x);
            ++tot;
            for(int i=;i<=m;++i)
                for(int j=;j<=i;++j)
                for(int k=;k<=L[x];++k)
                h[tot][i]=max(h[tot][i],h[tot-][j]+f[x][k][i-j]);
        }
    }
    for(int i=;i<=m;++i)
        ans=max(ans,h[tot][i]);
    printf("%d\n",ans);
}

BZOJ1017 树形DP的更多相关文章

  1. BZOJ1017 [JSOI2008]魔兽地图DotR 【树形dp + 背包dp】

    题目链接 BZOJ1017 题解 orz hzwer 树形dp神题 设\(f[i][j][k]\)表示\(i\)号物品恰好花费\(k\)金币,并将\(j\)个物品贡献给父亲的合成时的最大收益 计算\( ...

  2. 【BZOJ-1017】魔兽地图DotR 树形DP + 背包

    1017: [JSOI2008]魔兽地图DotR Time Limit: 30 Sec  Memory Limit: 162 MBSubmit: 1566  Solved: 705[Submit][S ...

  3. poj3417 LCA + 树形dp

    Network Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4478   Accepted: 1292 Descripti ...

  4. COGS 2532. [HZOI 2016]树之美 树形dp

    可以发现这道题的数据范围有些奇怪,为毛n辣么大,而k只有10 我们从树形dp的角度来考虑这个问题. 如果我们设f[x][k]表示与x距离为k的点的数量,那么我们可以O(1)回答一个询问 可是这样的话d ...

  5. 【BZOJ-4726】Sabota? 树形DP

    4726: [POI2017]Sabota? Time Limit: 20 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 128  Solved ...

  6. 树形DP+DFS序+树状数组 HDOJ 5293 Tree chain problem(树链问题)

    题目链接 题意: 有n个点的一棵树.其中树上有m条已知的链,每条链有一个权值.从中选出任意个不相交的链使得链的权值和最大. 思路: 树形DP.设dp[i]表示i的子树下的最优权值和,sum[i]表示不 ...

  7. 树形DP

    切题ing!!!!! HDU  2196 Anniversary party 经典树形DP,以前写的太搓了,终于学会简单写法了.... #include <iostream> #inclu ...

  8. BZOJ 2286 消耗战 (虚树+树形DP)

    给出一个n节点的无向树,每条边都有一个边权,给出m个询问,每个询问询问ki个点,问切掉一些边后使得这些顶点无法与顶点1连接.最少的边权和是多少.(n<=250000,sigma(ki)<= ...

  9. POJ2342 树形dp

    原题:http://poj.org/problem?id=2342 树形dp入门题. 我们让dp[i][0]表示第i个人不去,dp[i][1]表示第i个人去 ,根据题意我们可以很容易的得到如下递推公式 ...

随机推荐

  1. 基于口令的密码(PBE)

    基于口令的密码(PBE) 基于口令的密码(Password Based Encryption,PBE)是一种基于口令生成密钥,并使用该密钥进行加密的方法.其中加密和解密使用的是同一个密钥. 根据用户自 ...

  2. 斐波那契数列计算html代码

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. bootstrap-导航(垂直分组)

    1.运行效果如图所示 2.实现代码如下 <!DOCTYPE html> <html> <head>     <meta charset="utf-8 ...

  4. Qt之QListWidget:项目的多选与单选设置

    2019独角兽企业重金招聘Python工程师标准>>> #include "widget.h" #include <QApplication> #in ...

  5. [20170616]recover copy of datafile 6.txt

    [20170616]no copy of datafile 6 found to recover.txt --//最近几天一直被这个问题纠缠,我虽然不知道问题在哪来,还是找到简单的解决方法,做1个记录 ...

  6. Nginx SSL/HTTPS 配置

    使用OpenSSL生成证书 1.生成RSA密钥的方法 openssl genrsa -des3 -out privkey.pem 2048 这个命令会生成一个2048位的密钥,同时有一个des3方法加 ...

  7. CCF系列奖获奖名单公布,鲍虎军、周志华获CCF王选奖 | CNCC 2017

    本文讲的是CCF系列奖获奖名单公布,鲍虎军.周志华获CCF王选奖 | CNCC 2017, 由中国计算机学会(CCF)主办,福州市人民政府.福州大学承办,福建师范大学.福建工程学院协办的2017中国计 ...

  8. centos监控web目录www下的文件是否被黑、挂马的脚本

    .检查是否有安装inotify rpm -qa inotify-tools 2.没有先安装epol源 wget -O /etc/yum.repos.d/epel.repo http://mirrors ...

  9. 如何将MAC的 Terminal 行首变得清爽简洁一点?

    作为一位开发人员,MAC带给我们更好的编程体验,Terminal也是经常会去操作的东西,但是说实话,默认的 Terminal 的各种设置,真的让我好难受 刚开始打开,可能看到的会是这样的,行首一大堆东 ...

  10. 洛谷P1771 方程的解

    P1771 方程的解 都知道这个题可以用隔板法做 把这个\(g(x)\)想象为.....\(g(x)\)个苹果? 因为解是正整数,所以给这些"苹果"分组的时候每组最少有一个 然后我 ...