[bzoj1017]:[JSOI2008]魔兽地图DotR
2017-11-28 17:48
369 查看
传送门
JSOI2008 All Clear!
这个题简直了,我整个代码都是抄的,抄完还是一脸懵逼
我就tm没见过这么难的树形dp
一开始还以为水题,然后发现根本不知道怎么dp
题解还是直接抄hzwer的吧。。
设P[x],L[x],M[x],表示物品x的能量,购买上限与价格
L[x]=min(L[x],m/M[x])
高级装备的M和L随便dp一下
再用f[i][j][k]表示第i个物品,有j件用于上层的合成,花费金钱是k所能获得的最大力量
对于以x为根的子树,枚举合成 l 个 x 物品,然后再用其余的钱买一些 x 子树内的装备不用于合成
枚举合成物品数量 l ,用g[i][j]表示x的前i个儿子的子树,花费j的钱,所能获得的最大力量
g[tot][j]=max{g[tot-1][j-k]+f[e[i].to][l*e[i].v][k]}
//e[i].to是儿子结点,e[i].v是所需数量,就是从j中拿出k的钱在e[i].to的子树内购买
最后再枚举合成的 l 个 x 物品中有 j 个是直接用于增加力量,剩余用于合成的
f[x][j][k]=max{g[tot][k]+P[x]*(l-j)}
代码:
JSOI2008 All Clear!
这个题简直了,我整个代码都是抄的,抄完还是一脸懵逼
我就tm没见过这么难的树形dp
一开始还以为水题,然后发现根本不知道怎么dp
题解还是直接抄hzwer的吧。。
设P[x],L[x],M[x],表示物品x的能量,购买上限与价格
L[x]=min(L[x],m/M[x])
高级装备的M和L随便dp一下
再用f[i][j][k]表示第i个物品,有j件用于上层的合成,花费金钱是k所能获得的最大力量
对于以x为根的子树,枚举合成 l 个 x 物品,然后再用其余的钱买一些 x 子树内的装备不用于合成
枚举合成物品数量 l ,用g[i][j]表示x的前i个儿子的子树,花费j的钱,所能获得的最大力量
g[tot][j]=max{g[tot-1][j-k]+f[e[i].to][l*e[i].v][k]}
//e[i].to是儿子结点,e[i].v是所需数量,就是从j中拿出k的钱在e[i].to的子树内购买
最后再枚举合成的 l 个 x 物品中有 j 个是直接用于增加力量,剩余用于合成的
f[x][j][k]=max{g[tot][k]+P[x]*(l-j)}
代码:
#include<cstdio> #include<cstring> #include<iostream> #include<cmath> #include<algorithm> #include<cstdlib> #define ll long long using namespace std; inline int read(){ int x=0;char ch=' ';int f=1; while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar(); if(ch=='-')f=-1,ch=getchar(); while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar(); return x*f; } const int N=55,M=2005,K=105; struct edge{int to,next,l;}e[M]; int n,m,tot; int head ,f [K][M],g [M],h [M]; inline void addedge(int x,int y,int l){e[++tot].to=y;e[tot].next=head[x];head[x]=tot;e[tot].l=l;} int v ,cost ,mx ,in ,out ; inline void dp(int x){ if(!out[x]){ mx[x]=min(mx[x],m/cost[x]); for(int i=0;i<=mx[x];++i) for(int j=i;j<=mx[x];++j) f[x][i][j*cost[x]]=(j-i)*v[x]; return; } mx[x]=0x3f3f3f3f; for(int i=head[x];i;i=e[i].next){ int u=e[i].to; dp(u); mx[x]=min(mx[x],mx[u]/e[i].l); cost[x]+=cost[u]*e[i].l; } mx[x]=min(mx[x],m/cost[x]); memset(g,-0x3f,sizeof(g)); g[0][0]=0; for(int l=mx[x];l>=0;--l){ int tot=0; for(int i=head[x];i;i=e[i].next){ tot++; 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[e[i].to][l*e[i].l][k]); } for(int j=0;j<=l;++j) for(int k=0;k<=m;++k) f[x][j][k]=max(f[x][j][k],g[tot][k]+v[x]*(l-j)); } } int main(){ memset(f,-0x3f,sizeof(f)); n=read();m=read(); for(int i=1;i<=n;++i){ char ch[3]; v[i]=read(); scanf("%s",ch); if(ch[0]=='A'){ int C=read(); out[i]=C; while(C--){ int to=read(),num=read(); addedge(i,to,num); in[to]++; } } else cost[i]=read(),mx[i]=read(); } int tot=0; for(int x=1;x<=n;++x){ if(!in[x]){ tot++; dp(x); for(int i=0;i<=m;++i) for(int j=0;j<=i;++j) for(int k=0;k<=mx[x];++k) h[tot][i]=max(h[tot][i],h[tot-1][j]+f[x][k][i-j]); } } int ans=0; for(int i=0;i<=m;++i)ans=max(ans,h[tot][i]); printf("%d",ans); return 0; }
相关文章推荐
- 【BZOJ1017】[JSOI2008]魔兽地图DotR
- bzoj1017 [JSOI2008]魔兽地图DotR 树形DP
- 1017: [JSOI2008]魔兽地图DotR - BZOJ
- [bzoj1017][JSOI2008]魔兽地图DotR【dp】
- [BZOJ1017][JSOI2008]魔兽地图DotR 树形dp
- bzoj 1017: [JSOI2008]魔兽地图DotR【树形dp+背包】
- [bzoj1017][JSOI2008]魔兽地图 DotR (Tree DP)【有待优化】
- [JSOI2008][BZOJ1017] 魔兽地图DotR|树型dp
- BZOJ.1017.[JSOI2008]魔兽地图(树形DP 背包DP)
- 【树形Dp】【JSOI2008】【BZOJ1017魔兽地图DotR】
- [bzoj1017]: [JSOI2008]魔兽地图DotR
- BZOJ1017 [JSOI2008]魔兽地图DotR 【树形dp + 背包dp】
- bzoj 1017: [JSOI2008]魔兽地图DotR (树形DP+多重背包)
- 【East!模拟赛】【Round1】【BZOJ1017】魔兽地图Dotr 树形DP
- [BZOJ1017][JSOI2008]魔兽地图DotR-动态规划
- 【bzoj1017】[JSOI2008]魔兽地图DotR
- [BZOJ1017][JSOI2008][树形DP]魔兽地图DotR
- 【树形背包】【JSOI 2008】【bzoj 1017】魔兽地图DotR
- bzoj1017 [JSOI2008]魔兽地图DotR(树形dp+背包dp+剪枝)
- bzoj 1017 : [JSOI2008]魔兽地图DotR