【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里面的英雄只有一个属性——力量。他们需要购买装备来提升自己的力量值,每件装备都可以使佩戴它的英雄的力量值提高固定的点数,所以英雄的力量值等于它购买的所有装备的力量值之和。装备分为基本装备和高级装备两种。基本装备可以直接从商店里面用金币购买,而高级装备需要用基本装备或者较低级的高级装备来合成,合成不需要附加的金币。装备的合成路线可以用一棵树来表示。比如,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

比较麻烦的树形dp。

注意题目中说了:合成的过程一定是满足一棵树的形状的!

dp方程:

f[i][j][k]表示第i个装备花k的钱,贡献j个给上级的最大力量,g[tot][j]表示当前是i的第tot个儿子,一共花费j的钱的最大力

量。

在这两个方程之上,我们需要嵌套一层循环all,表示第i个装备要做多少个。

那么我们先求g数组(要满足能做all个i):

g[tot][j]=max(g[tot-1][j],g[tot-1][j-k]+f[y][all*num[tot]][k])

(k是花多少的钱做当前的儿子,y是当前儿子的编号,num[tot]表示做1个i用几个tot)

在当前的now下继续求f数组:

f[i][j][k]=max(f[i][j][k],g[tot][k]+p[i]*(all-j))

注意:

now要从大到小循环,保证g数组是单增的,就可以避免每次清空g数组了。

<span style="font-size:18px;">#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#define inf 0x3f3f3f3f
using namespace std;
int in[60],h[60],tot=0,n,m,g[60][2005],l[60],p[60],c[60],f[60][106][2005];
struct edge
{
	int y,ne,num;
}e[200005];
void Addedge(int x,int y,int v)
{
	tot++;
	e[tot].y=y;
	e[tot].ne=h[x];
	h[x]=tot;
	e[tot].num=v;
	in[y]++;
}
void dp(int x)
{
	if (!h[x])
	{
		l[x]=min(l[x],m/c[x]);
		for (int i=0;i<=l[x];i++)
			for (int j=i;j<=l[x];j++)
				f[x][i][j*c[x]]=p[x]*(j-i);
		return;
	}
	l[x]=m;
	for (int i=h[x];i;i=e[i].ne)
	{
		int y=e[i].y;
		dp(y);
		l[x]=min(l[x],l[y]/e[i].num);
		c[x]+=e[i].num*c[y];
	}
	l[x]=min(l[x],m/c[x]);
	for (int i=1;i<=n;i++)
		for (int j=0;j<=m;j++)
			g[i][j]=-inf;
	g[0][0]=0;
	for (int all=l[x];all>=0;all--)
	{
		int tot=0;
		for (int i=h[x];i;i=e[i].ne)
		{
			tot++;
			int y=e[i].y;
			for (int j=0;j<=m;j++)
				for (int k=0;k<=j;k++)
					g[tot][j]=max(g[tot][j],g[tot-1][j-k]+f[y][all*e[i].num][k]);
		}
		for (int i=0;i<=all;i++)
			for (int k=0;k<=m;k++)
				f[x][i][k]=max(f[x][i][k],g[tot][k]+p[x]*(all-i));
	}
}
int main()
{
        scanf("%d%d",&n,&m);
	for (int i=1;i<=n;i++)
		for (int j=0;j<=105;j++)
			for (int k=0;k<=m;k++)
				f[i][j][k]=-inf;
	for (int i=1;i<=n;i++)
	{
		scanf("%d",&p[i]);
		char s[5];
		scanf("%s",s);
		if (s[0]=='B') scanf("%d%d",&c[i],&l[i]);
		else
		{
			int k;
			scanf("%d",&k);
			while(k--)
			{
				int y,v;
				scanf("%d%d",&y,&v);
				Addedge(i,y,v);
			}
		}
	}
	int ans=0;
	for (int i=1;i<=n;i++)
		if (!in[i])
		{
			dp(i);
			for (int j=0;j<=m;j++)
				for (int k=0;k<=l[i];k++)
					ans=max(ans,f[i][k][j]);
			break;
		}
	cout<<ans<<endl;
	return 0;
}
</span>

感悟:

1.这道题f[i][j][k]这种转移方式中j表示给上级几个,这种转移方式还是第一次见!

2.这道题vfk有二维解法,以后看看

时间: 2024-10-18 12:58:32

【BZOJ 1017】 [JSOI2008]魔兽地图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(树形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][

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里面的英雄只有一个属性——力

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

[JSOI2008][BZOJ1017] 魔兽地图DotR|树形动规

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

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

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

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

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

BZOJ 1017 魔兽地图DotR(树形DP)

题意:有两类装备,高级装备A和基础装备B.现在有m的钱.每种B有一个单价和可以购买的数量上限.每个Ai可以由Ci种其他物品合成,给出Ci种其他物品每种需要的数量.每个装备有一个贡献值.求最大的贡献值.已知物品的合成路线是一个严格的树模型.即有一种物品不会合成其他任意物品,其余物品都会仅仅可用作合成另外一种物品 思路:f[i][j][k],代表第i个物品,花费了j,向上提供k个i物品. 1 #include<algorithm> 2 #include<cstdio> 3 #inclu