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

看见我机房的小伙伴没写,我又不能问他,BZOJ上这又不是一道不可做题,不想跳过这道题,于是就写了

题解一共也就两种,一个是VFleaKing的,另一个是普通的树dp

看题解看不懂啊,囧,没办法,我就是这么弱........

于是先打暴力,f[i,j,k]表示节点i买了j个,用了k元钱的最大力量值

然后树dp之,对于每一个j,先强制买好j个i物品,然后k元钱里剩下的去做背包(从i的儿子里面选,用合成剩余的部分来做01背包)

暴力好不容易打出来(细节没注意,囧,写了一两个小时暴力,之前还想抄C++代码,可惜不怎么懂,勉强翻译过来连样例都过不了)

暴力肯定是要超时的(我自测,有的点100s都跑不出),不过我发现了一个优化

 const
maxn=;
maxm=;
var
w,gold,lim,num,max1,fa,first:array[..maxn]of longint;
next,last:array[..maxn*]of longint;
f:array[..maxn,..,..maxm]of longint;
n,m,ans,tot:longint; procedure insert(x,y,z:longint);
begin
inc(tot);
last[tot]:=y;
next[tot]:=first[x];
first[x]:=tot;
num[tot]:=z;
fa[y]:=x;
end; function max(x,y:longint):longint;
begin
if x>y then exit(x);
exit(y);
end; function min(x,y:longint):longint;
begin
if x<y then exit(x);
exit(y);
end; procedure dfs(x:longint);
var
i,j,k,l,v:longint;
begin
if first[x]= then
begin
max1[x]:=min(lim[x],m div gold[x]);
for i:= to max1[x] do
begin
f[x,i,i*gold[x]]:=w[x]*i;
ans:=max(ans,f[x,i,i*gold[x]]);
end;
exit;
end;
max1[x]:=maxm;
i:=first[x];
while i<> do
begin
dfs(last[i]);
max1[x]:=min(max1[x],max1[last[i]] div num[i]);
inc(gold[x],num[i]*gold[last[i]]);
i:=next[i];
end;
for i:= to max1[x] do
begin
l:=first[x];
for j:=i*gold[x] to m do
f[x,i,j]:=w[x]*i;
l:=first[x];
while l<> do
begin
for j:=m downto i*gold[x] do
for k:=num[l]*i to max1[last[l]] do
for v:=(k-num[l]*i)*gold[last[l]] to j-i*gold[x] do
f[x,i,j]:=max(f[x,i,j],f[x,i,j-v]+f[last[l],k,v+num[l]*i*gold[last[l]]]-num[l]*i*w[last[l]]);
l:=next[l];
end;
for j:=i*gold[x] to m do
ans:=max(ans,f[x,i,j]);
end;
end; procedure main;
var
i,j,k,x,y:longint;
s:char;
begin
read(n,m);
for i:= to n do
begin
read(w[i]);
read(s,s);
if s='B' then read(gold[i],lim[i])
else
begin
read(k);
for j:= to k do
begin
read(x,y);
insert(i,x,y);
end;
end;
end;
for i:= to n do
if fa[i]= then dfs(i);
writeln(ans);
end; begin
main;
end.

暴力

                 for j:=m downto i*gold[x] do
for k:=num[l]*i to max1[last[l]] do
for v:=(k-num[l]*i)*gold[last[l]] to j-i*gold[x] do
f[x,i,j]:=max(f[x,i,j],f[x,i,j-v]+f[last[l],k,v+num[l]*i*gold[last[l]]]-num[l]*i*w[last[l]]);

在这里,我们枚举的太多,其实只要满足k>=num[l]*i就行了

于是我们做完后可以对f数组做一些处理,使f数组的f[i,j,k]表示i物品买了j个以上,用了k元钱的最大力量

所以每次做完,我们都做一遍下面这个处理

             for k:=max1[x] downto  do
for v:=gold[x]*k to m do
up(f[x,k-,v],f[x,k,v]);

只不过做完这个,我就想不出什么优化了,卡了好久,用cena自测总时间20s左右,BZOJ上就是过不了

过了好久,期间想过各种底层优化,可惜不懂,所以就没写了

然后发现一个很无语的优化,自测总时间6s多

对于每一个点,计算一下这颗子树最多用多少钱,记为lim[x],这样就不用每次都枚举到m了

 /**************************************************************
Problem:
User: 1997cb
Language: Pascal
Result: Accepted
Time: ms
Memory: kb
****************************************************************/ const
maxn=;
maxm=;
var
w,gold,num,max1,fa,first,lim:array[..maxn]of longint;
next,last:array[..maxn*]of longint;
f:array[..maxn,..,..maxm]of longint;
n,m,ans,tot:longint; procedure insert(x,y,z:longint);
begin
inc(tot);
last[tot]:=y;
next[tot]:=first[x];
first[x]:=tot;
num[tot]:=z;
fa[y]:=x;
end; procedure up(var x:longint;y:longint);
begin
if x<y then x:=y;
end; procedure down(var x:longint;y:longint);
begin
if x>y then x:=y;
end; procedure dfs(x:longint);
var
i,j,k,l,v:longint;
begin
if first[x]= then
begin
down(max1[x],trunc(m/gold[x]));
lim[x]:=max1[x]*gold[x];
for i:= to max1[x] do
f[x,i,i*gold[x]]:=w[x]*i;
for k:=max1[x] downto do
for v:=gold[x]*k to m do
up(f[x,k-,v],f[x,k,v]);
exit;
end;
max1[x]:=maxm;
i:=first[x];
while i<> do
begin
dfs(last[i]);
inc(lim[x],lim[last[i]]);
down(max1[x],trunc(max1[last[i]]/num[i]));
inc(gold[x],num[i]*gold[last[i]]);
i:=next[i];
end;
down(lim[x],m);
for i:= to max1[x] do
begin
l:=first[x];
for j:=i*gold[x] to lim[x] do
f[x,i,j]:=w[x]*i;
l:=first[x];
while l<> do
begin
k:=num[l]*i;
for j:=lim[x] downto i*gold[x] do
for v:= to j-i*gold[x] do
up(f[x,i,j],f[x,i,j-v]+f[last[l],k,v+k*gold[last[l]]]-k*w[last[l]]);
l:=next[l];
end;
for k:=max1[x] downto do
for v:=gold[x]*k to lim[x] do
up(f[x,k-,v],f[x,k,v]);
end;
end; procedure main;
var
i,j,k,x,y:longint;
s:char;
begin
read(n,m);
for i:= to n do
begin
read(w[i]);
read(s,s);
if s='B' then read(gold[i],max1[i])
else
begin
read(k);
for j:= to k do
begin
read(x,y);
insert(i,x,y);
end;
end;
end;
for i:= to n do
if fa[i]= then
begin
dfs(i);
for j:= to max1[i] do
up(ans,f[i,j,lim[i]]);
end;
writeln(ans);
end; begin
main;
end.

最终版

1017: [JSOI2008]魔兽地图DotR - BZOJ的更多相关文章

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

    bzoj上是一个森林啊--? dp还是太弱了 设f[i][j][k]为到点i,合成j个i并且花费k金币能获得的最大力量值,a[i]为数量上限,b[i]为价格,p[i]为装备力量值 其实这个状态设计出来 ...

  2. bzoj 1017 : [JSOI2008]魔兽地图DotR

    比较难想的的一道树形dp. 看到这道题正常的思路应该是$f[i][j][k]$表示i这棵子树里买了j个i物品花费为k的最大收益. 但如果直接这么定义的话转移复杂度会很高,需要枚举j,枚举孩子,枚举k, ...

  3. BZOJ [JSOI2008]魔兽地图DotR

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

  4. 【bzoj1017】[JSOI2008]魔兽地图DotR

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

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

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

  6. [bzoj1017][JSOI2008]魔兽地图 DotR (Tree DP)【有待优化】

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

  7. BZOJ1017: [JSOI2008]魔兽地图DotR【树形DP】【玄学】

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

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

    [题目链接]:http://www.lydsy.com/JudgeOnline/problem.php?id=1017 [题意] [题解] 设f[i][j][k] 表示第i个节点以下的总花费为j, 然 ...

  9. BZOJ.1017.[JSOI2008]魔兽地图(树形DP 背包DP)

    题目链接 树形DP,考虑子节点对父节点的贡献. 设f[x][i][j]表示当前为x,用i个x去合成上一层装备,花费为j的最大价值. 由子节点转移时 是一个分组背包,需要一个辅助数组g[i][j]表示前 ...

随机推荐

  1. 第五十二篇、 OC获取视频的第一帧图片thumbnailImage

    获取视频的第一帧图片 有时候我们拍摄完视频后,希望获取一张图片当作这个视频的介绍,这个图片thumbnailImage可以从视频的第一帧获取到. 我们的思路是先获取视频的URL,然后初始化一个MPMo ...

  2. jQuery学习一:jQuery中的ready和load事件

    //ready事件 $(document).ready(function(){ 代码........ }); //ready事件简写: $(function(){ 代码........ }); //l ...

  3. 方法:怎么用ionic命令行调试你的ionic app

    官网上有很详细的解说  http://blog.ionic.io/live-reload-all-things-ionic-cli/ 下面说说我自己的调试过程(android版): 首先用命令行进入你 ...

  4. 我们一起学Windows Phone 8-01-开发环境搭建

    我们仅讨论Windows Phone 8的开发,不考虑兼容向下兼容.也不会提供任何盗版软件的下载.破解. 需要准备 知识:.NET相关开发经验,C#语言开发经验.如果有WPF或Silverlight开 ...

  5. linux命令之vim使用-(转)vim的保存文件和退出命令

    博客地址: http://blog.sina.com.cn/s/blog_5e357d2d0100zmth.html

  6. mysql 不能远程连接

    不想浪费大家时间,我这文章记录了我在vagrant上架的mysql远程连接不上的问题,不过我在整理时发现这个下面这个链接,如果我一开始能找到这个我就不会绕那么多弯了.不想看我是怎么一步步调错过程的请直 ...

  7. Git 安装与使用(二)

    一.分支管理 在Git里,master是主分支,同时可以创建其他分支,支持各分支合并到主分支上,基本命令如下 1.创建分支 git checkout -b dev       创建dev分支,并切换到 ...

  8. 将C# dataTable 做为参数传入到存储过程

    1.list转换为DataTable(如果有需要) public static DataTable ListToDataTable<T>(List<T> entitys) { ...

  9. iterm2 配色修改

    打开终端 输入 cd ~ vim .bash_profile 插入 export CLICOLOR= export LSCOLORS=gxfxcxdxbxegedabagacad export PS1 ...

  10. C#调用IOS推送

    C#调用IOS推送 使用的是 PushSharp 开源库 源码代码如下 点我