其实这题是我从noip前就开始做的。。。那个时候打的Pascal,一直TLE,转了C++之后我又写了一遍,A了。。。

辛酸史:

                    

题目描述:

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

数据范围:物品数(n)<=51,金币数(m)<=2000,限购数量(limit)<=100。

思路分析:

可以说是一道树上背包DP吧。

观察题目,注意到:限购数量是题目的关键,对于一个物品,它合成几件,或是把几件用于父亲装备的合成,是题目恶心的地方,既然这样的话我们就把它设计到状态里面。然后再看看数据范围,限购小于等于100——很明显了,出题人就是想让我们把限购数量放进状态里面。再和普通的背包结合一下,得到状态,f[u][i][j]表示:对于以u为根的子树,在以u为根的子树上,我们投入i个金币,并且把j个物品u用于父亲装备的合成,以u为根的子树能产生的最大力量值。

然后我们还需要一个g数组来辅助f数组的转移。g[i][j]表示:对于u的前i个儿子装备,在以它们为根的子树中投入j个金币,能得到的最大力量值。

转移时我们需要枚举的很重要的一环就是:制作几个u装备,从而让整个转移能够顺利地进行下去,我们把它设为l。

得到g数组的转移:g[i][j]=max(g[i][j],g[i-1][j-k]+f[v][k][l*need])       其中v为u的第i个儿子,而need则为制作一个装备u需要几个装备v,k为在以v为根的子树中花费k个金币。

通过g数组的转移,继而得到f数组的转移:f[u][i][j]=max(f[u][i][j],g[siz[u]][i]+w[u]*(l-j))       其中siz[u]表示u有几个儿子。

最后求答案的时候我们又需要一个dp数组来求解。(嗯,没错,一道题目,三个背包dp,我也不得不佩服出题人了——你是真TM的毒瘤!

最后这个就是最简单的背包dp了(如果这个都想不到的话,建议你前往xx省xx市实验学校,和某张姓老师学习一段时间)

状态dp[i][j],表示前i个“终极装备”(终极装备就是无法用于合成的装备),花费j个金币,能得到的最大力量值。转移的时候枚举一下在第i个装备上花费多少金币就可以了,具体不懂的话还是看代码吧,太简单了,也不想多讲了。

代码实现:

#include<bits/stdc++.h>
using namespace std;
const int inf=1000000000;
int f[55][2005][105],g[55][2005],dp[55][2005];
int a[55][55],need[55][55],limit[55],cost[55],w[55],siz[55];
bool root[55],son[55];
int n,m;
void dfs(int u){
if (!son[u]){
limit[u]=min(limit[u],m/cost[u]);
for (int i=0;i<=limit[u];i++)
for (int j=0;j<=i;j++)
f[u][i*cost[u]][j]=w[u]*(i-j);
return;
}
limit[u]=inf;
for (int i=1;i<=siz[u];i++){
dfs(a[u][i]);
cost[u]+=cost[a[u][i]]*need[u][i];
limit[u]=min(limit[u],limit[a[u][i]]/need[u][i]);
}
limit[u]=min(limit[u],m/cost[u]);
memset(g,-0x3f,sizeof(g));
g[0][0]=0;
for (int l=limit[u];l>=0;l--){ //这里倒着枚举l,是为了避免多次给g数组赋初值
for (int i=1;i<=siz[u];i++)
for (int j=0;j<=m;j++)
for (int k=0;k<=j;k++)
g[i][j]=max(g[i][j],g[i-1][j-k]+f[a[u][i]][k][l*need[u][i]]);
for (int i=0;i<=l;i++)
for (int j=0;j<=m;j++)
f[u][j][i]=max(f[u][j][i],g[siz[u]][j]+w[u]*(l-i));
}
}
int main(){
memset(f,-0x3f,sizeof(f));
scanf("%d%d",&n,&m);
int nn,ans=0;
for (int i=1;i<=n;i++){
scanf("%d",&w[i]);
char ch[3]; scanf("%s",&ch);
if (ch[0]=='A'){
scanf("%d",&nn);
for (int j=1;j<=nn;j++) scanf("%d%d",&a[i][j],&need[i][j]),root[a[i][j]]=true;
son[i]=true; siz[i]=nn;
} else scanf("%d%d",&cost[i],&limit[i]);
}
int now=0;
for (int i=1;i<=n;i++)
if (!root[i]){
dfs(i); now++;
for (int j=0;j<=m;j++)
for (int k=0;k<=j;k++)
dp[now][j]=max(dp[now][j],dp[now-1][j-k]+f[i][k][0]);
}
for (int i=0;i<=m;i++) ans=max(ans,dp[now][i]);
printf("%d\n",ans);
return 0;
}

JSOI 2008 【魔兽地图】的更多相关文章

  1. JSOI 2008 魔兽地图

    题目描述 DotR (Defense of the Robots) Allstars是一个风靡全球的魔兽地图,他的规则简单与同样流行的地图DotA (Defense of the Ancients) ...

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

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

  3. 1017: [JSOI2008]魔兽地图DotR - BZOJ

    Description DotR (Defense of the Robots) Allstars是一个风靡全球的魔兽地图,他的规则简单与同样流行的地图DotA (Defense of the Anc ...

  4. BZOJ 1017 魔兽地图

    Description DotR (Defense of the Robots) Allstars是一个风靡全球的魔兽地图,他的规则简单与同样流行的地图DotA (Defense of the Anc ...

  5. BZOJ [JSOI2008]魔兽地图DotR

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

  6. 【百度地图API】如何制作一张魔兽地图!!——CS地图也可以,哈哈哈

    原文:[百度地图API]如何制作一张魔兽地图!!--CS地图也可以,哈哈哈 摘要: 你玩魔兽不?你知道如何做一张魔兽地图不?! 快来看此文吧! ---------------------------- ...

  7. [BZOJ]1017 魔兽地图DotR(JSOI2008)

    BZOJ第一页做着做着就能碰到毒题,做到BZOJ1082小C就忍了,没想到下一题就是这种东西.这种题目不拖出来枭首示众怎么对得起小C流逝的青春啊. Description DotR (Defense ...

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

    DotR (Defense of the Robots) Allstars是一个风靡全球的魔兽地图,他的规则简单与同样流行的地图DotA (Defense of the Ancients) Allst ...

  9. 【BZOJ1017】[JSOI2008]魔兽地图(动态规划)

    [BZOJ1017][JSOI2008]魔兽地图(动态规划) 题面 BZOJ 洛谷 题解 状态设一下,\(f[i][j][k]\)表示第\(i\)个物品,有\(j\)个用于合成,总花费为\(k\)的最 ...

随机推荐

  1. unity3d插入android有米广告

    有米官网:http://www.youmi.net/register?r=MTI0MDg= 国内的广告,我觉得万普和有米还不错,我也只试了这两个,其他的都是看评价的,呵呵~~~首先我们去有米官网注册一 ...

  2. Codeforces1250C Trip to Saint Petersburg 线段树

    题意 有个人要去圣彼得堡旅游,在圣彼得堡每天要花\(k\)块钱,然后在圣彼得堡有\(n\)个兼职工作\(l_i,r_i,p_i\),如果这个人在\(l_i\)到\(r_i\)这个时间段都在圣彼得堡,那 ...

  3. 持续部署入门:基于 Kubernetes 实现蓝绿发布

    前言 软件世界比以往任何时候都更快.为了保持竞争力,需要尽快推出新的软件版本,而不会中断活跃用户访问,影响用户体验.越来越多企业已将其应用迁移到 Kubernetes. 在 Kubernetes 中有 ...

  4. C:将算术表达式的符号和数分开

    程序: #include <stdio.h> #include <string.h> static int pos=; static char* line; void test ...

  5. uap设置gradle和jdk

  6. [Oracle/Sql] Decode与Case

    Decode和case都可以实现SQL中的条件结构,下面为用法示例: select id,name,score,decode(floor(score/20),5,'A',4,'B',3,'C',2,' ...

  7. Java查找指定文件中指定字符的个数

    package lwl.youweb2.test; import java.io.BufferedReader; import java.io.FileReader; import java.io.I ...

  8. Windows7上开启ftp服务器功能

    开启ftp服务功能   1 进入“控制面板”->“程序”->"打开或关闭Windows功能",找到“Internet信息服务”选项 2 将“Internet信息服务”选 ...

  9. request的各种方法

    protected void doPost(HttpServletRequest request, HttpServletResponse response)        throws Servle ...

  10. oracle之三rman 不完全恢复

    rman 不完全恢复 9.1 rman 不完全恢复的三个标准模式:基于time.基于scn和基于sequence: 范例1:恢复过去某个时间点误操作,一般使用基于time或scn. 1)环境:有一套全 ...