[JSOI2008]魔兽地图(树形dp)

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

Solution

极强的一道树形dp题。

我们设dp[i][j][k]表示当前正在做以i为根的子树,我们需要用j个物品用于向上合成,花费了k元能够获得的最大收益。

首先我们可以递归回溯求出每个点的价格和他的限制购买次数(这个东西是和儿子节点相关的)。

然后就枚举向上传多少个物品,在这里我们记录一个辅助数组g[i][j]表示做到了第i棵子树,背包体积为j时能够获得的最大收益。

但它可能有多个联通块,做完每个子树后我们再把它合并到一个数组里就可以了。

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#define inf 1e9
#define N 55
#define M 2010
using namespace std;
int dp[N][N<<1][M],g[N][M],head[N],w[N],va[N],l[N],f[N][M],tot,m,n,ji[N];
struct efr{
    int n,to,l;
}an[20009];
inline void add(int u,int v,int l){
    an[++tot].n=head[u];
    an[tot].to=v;
    an[tot].l=l;
    head[u]=tot;
}
void dfs(int u){
    if(!head[u]){
        l[u]=min(l[u],m/va[u]);//这里求出这件物品的购买限制
        for(int i=0;i<=l[u];++i)
           for(int j=i;j<=l[u];++j)
              dp[u][i][j*va[u]]=(j-i)*w[u];//j 表示买了多少个
        return;
    }
    l[u]=inf;
    for(int i=head[u];i;i=an[i].n){
        int v=an[i].to;
        dfs(v);
        l[u]=min(l[u],l[v]/an[i].l);//更新l得知
        va[u]+=va[v]*an[i].l;//在这里递归计算u的价值
    }
    l[u]=min(l[u],m/va[u]);
    memset(g,-0x3f,sizeof(g));
    g[0][0]=0;
    for(int o=l[u];o>=0;--o){//枚举上传几个
        int cnt=0;
        for(int i=head[u];i;i=an[i].n){
         int v=an[i].to;
         cnt++;
        for(int j=m;j>=0;--j)
          for(int k=0;k<=j;++k)
            g[cnt][j]=max(g[cnt][j],g[cnt-1][j-k]+dp[v][o*an[i].l][k]);
        }
        for(int i=0;i<=o;++i)
          for(int j=0;j<=m;++j)
             dp[u][i][j]=max(dp[u][i][j],g[cnt][j]+w[u]*(o-i));
    }
}
inline char rd(){
    char c=getchar();
    while(c!=‘A‘&&c!=‘B‘)c=getchar();
    return c;
}
int main(){
    scanf("%d%d",&n,&m);
    memset(dp,-0x3f,sizeof(dp));
    char c;
    for(int i=1;i<=n;++i){
        scanf("%d",&w[i]);
        c=rd();
        if(c==‘B‘)scanf("%d%d",&va[i],&l[i]);
        else{
            int x,y,z;
            scanf("%d",&x);
            for(int j=1;j<=x;++j){
               scanf("%d%d",&y,&z);
               add(i,y,z);
               ji[y]=1;
            }
        }
    }
    int cnt=0;
    for(int i=1;i<=n;++i)
      if(!ji[i]){
          dfs(i);
          cnt++;
          for(int j=0;j<=m;++j)
            for(int k=0;k<=j;++k)
              f[cnt][j]=max(f[cnt][j],f[cnt-1][j-k]+dp[i][0][k]);
      }
   int ans=0;
   for(int i=0;i<=m;++i)
     ans=max(ans,f[cnt][i]);
   cout<<ans;
    return 0;
} 

原文地址:https://www.cnblogs.com/ZH-comld/p/9813050.html

时间: 2024-10-11 06:14:12

[JSOI2008]魔兽地图(树形dp)的相关文章

[luogu4037 JSOI2008] 魔兽地图 (树形dp)

传送门 Description DotR (Defense of the Robots) Allstars是一个风靡全球的魔兽地图,他的规则简单与同样流行的地图DotA (Defense of the Ancients) Allstars. DotR里面的英雄只有一个属性--力量.他们需要购买装备来提升自己的力量值,每件装备都可以使佩戴它的英雄的力量值提高固定的点数,所以英雄的力量值等于它购买的所有装备的力量值之和.装备分为基本装备和高级装备两种.基本装备可以直接从商店里面用金币购买,而高级装备

bzoj 1017[JSOI2008]魔兽地图DotR - 树形dp

1017: [JSOI2008]魔兽地图DotR Time Limit: 30 Sec  Memory Limit: 162 MB Description DotR (Defense of the Robots) Allstars是一个风靡全球的魔兽地图,他的规则简单与同样流行的地图DotA (Defense of the Ancients) Allstars.DotR里面的英雄只有一个属性--力量.他们需要购买装备来提升自己的力量值,每件装备都可以使佩戴它的英雄的力量值提高固定的点数,所以英雄

【BZOJ 1017】 [JSOI2008]魔兽地图DotR

1017: [JSOI2008]魔兽地图DotR Time Limit: 30 Sec  Memory Limit: 162 MB Submit: 1069  Solved: 433 [Submit][Status] Description DotR (Defense of the Robots) Allstars是一个风靡全球的魔兽地图,他的规则简单与同样流行的地图DotA (Defense of the Ancients) Allstars.DotR里面的英雄只有一个属性--力量.他们需要购

BZOJ 1017--魔兽地图(树形DP&amp;完全背包)

1017: [JSOI2008]魔兽地图DotR Time Limit: 30 Sec  Memory Limit: 162 MBSubmit: 2674  Solved: 1041[Submit][Status][Discuss] Description DotR (Defense of the Robots) Allstars是一个风靡全球的魔兽地图,他的规则简单与同样流行的地图DotA (Defense of the Ancients) Allstars.DotR里面的英雄只有一个属性——

BZOJ [JSOI2008]魔兽地图DotR

1017: [JSOI2008]魔兽地图DotR Time Limit: 30 Sec  Memory Limit: 162 MBSubmit: 1243  Solved: 532[Submit][Status][Discuss] Description DotR (Defense of the Robots) Allstars是一个风靡全球的魔兽地图,他的规则简单与同样流行的地图DotA (Defense of the Ancients) Allstars.DotR里面的英雄只有一个属性——力

[BZOJ 1017][JSOI2008]魔兽地图DotR(树形Dp)

Description DotR (Defense of the Robots) Allstars是一个风靡全球的魔兽地图,他的规则简单与同样流行的地图DotA (Defense of the Ancients) Allstars.DotR里面的英雄只有一个属性——力量.他们需要购买装备来提升自己的 力量值,每件装备都可以使佩戴它的英雄的力量值提高固定的点数,所以英雄的力量值等于它购买的所有装备的力 量值之和.装备分为基本装备和高级装备两种.基本装备可以直接从商店里面用金币购买,而高级装备需要用

bzoj 1017 : [JSOI2008]魔兽地图DotR

比较难想的的一道树形dp. 看到这道题正常的思路应该是$f[i][j][k]$表示i这棵子树里买了j个i物品花费为k的最大收益. 但如果直接这么定义的话转移复杂度会很高,需要枚举j,枚举孩子,枚举k,枚举孩子的花费,还要枚举每个孩子各买了多少件. 想办法把最后一个循环去掉. 重新定义状态$f[i][j][k]$表示表示i这棵子树里至少买了j个i物品花费为k的最大收益. 每次枚举完物品数量后加上这么一句 if(i!=l[x])f[x][i][j]=max(f[x][i][j],f[x][i+1][

[JSOI2008]魔兽地图

树上背包 题目传送门 首先,有没有哪位dalao 愿意告诉我为什么合成高级装备不需要附加金币,, 好吧,这个不重要 明确表示装备合成路线可以用一棵树来表示.一颗?傻乎乎的在下之前每次就只dp一棵树,不出意外的WA了,,在看几遍,好嘛,好像是个森林啊(泪奔) 最容易想到的dp[x][i][j]是第x件买了i个,花了j元的最高力量.但是,,这样好像就成为不可做题了(欢迎各路dalao打脸,反正不是我说的[手动滑稽](偷偷扔出FYJ挡枪)),那么换一种思路,还是dp[x][i][j],但表示的是第x件

BZOJ1017: [JSOI2008]魔兽地图DotR

传送门 设$f[i][j][k]$表示对于第$i$个点,向父节点贡献$j$个已合成的装备,花费了$k$的代价,最多获得的力量值. 单纯的$f[i][j][k]$是很难转移的,主要原因是无法维护和其他儿子的关系.所以对于每个节点再搞一个$g[i][j]$表示当前点的前$i$个儿子花费为$k$可以获得的最大的力量值. 然后肯定要先更新$g[][]$再以$g[][]$来更新$f[][][]$. 列出$g[i][j]$的状态转移方程就是: $g[cnt][k]=max \{ f[son][tol \ti