每个装备可以直接贡献,也可以用于合成
设
f
[
i
]
[
j
]
[
k
]
f[i][j][k]
f[i][j][k]表示第
i
i
i件装备,
j
j
j件用于合成,花费
k
k
k元可以获得的最大力量值
首先处理出每个高级物品能够购买的上限
l
i
m
[
i
]
lim[i]
lim[i]和价格
m
o
n
[
i
]
mon[i]
mon[i]
枚举每个物品购买的数量
l
l
l
f
f
f数组不好直接转移,设
g
[
i
]
[
j
]
g[i][j]
g[i][j]表示当前子树的前
i
i
i个子树,花费
j
j
j元的最大值,转移就是
g
[
t
o
t
]
[
j
]
=
m
a
x
(
g
[
t
o
t
]
[
j
]
,
g
[
t
o
t
−
1
]
[
j
−
k
]
+
f
[
t
o
[
i
]
]
[
l
∗
n
e
d
[
i
]
]
[
k
]
)
;
g[tot][j]=max(g[tot][j],g[tot-1][j-k]+f[to[i]][l*ned[i]][k]);
g[tot][j]=max(g[tot][j],g[tot−1][j−k]+f[to[i]][l∗ned[i]][k]);
然后
f
f
f的转移就出来了:
f
[
x
]
[
i
]
[
j
]
=
m
a
x
(
f
[
x
]
[
i
]
[
j
]
,
g
[
t
o
t
]
[
j
]
+
p
o
w
e
r
[
x
]
∗
(
l
−
i
)
)
;
f[x][i][j]=max(f[x][i][j],g[tot][j]+power[x]*(l-i));
f[x][i][j]=max(f[x][i][j],g[tot][j]+power[x]∗(l−i));
最后,因为这实际上是一片森林,所以再背包一次选最大值
P.S.实际上BZOJ第8个点跑的很慢,不过我看网上的题解很多都这样
Code:
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(fast)
#include<bits/stdc++.h>
using namespace std;
const int rlen=1<<18|1;
inline char gc(){
static char buf[rlen],*ib,*ob;
(ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
return ib==ob?-1:*ib++;
}
inline int read(){
int ans=0;
char ch=gc();
while(!isdigit(ch))ch=gc();
while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
return ans;
}
const int N=55,M=2005,INF=1e9;
int vis[N<<1],head[N<<1],nxt[N<<1],tot=0,ned[N<<1],in[N];
inline void add(int x,int y,int w){vis[++tot]=y;nxt[tot]=head[x];head[x]=tot;ned[tot]=w;++in[y];}
int f[N][N<<1][M],g[N][M],dp[N][M];
int lim[N],val[N],mon[M];
int n,m,cnt;
char c;
void dfs(int x){
if(!head[x]){
lim[x]=min(lim[x],m/mon[x]);
for(int i=0;i<=lim[x];i++)
for(int j=i;j<=lim[x];j++)
f[x][i][j*mon[x]]=(j-i)*val[x];
return;
}
lim[x]=INF;
for(int i=head[x];i;i=nxt[i]){
dfs(vis[i]);
lim[x]=min(lim[x],lim[vis[i]]/ned[i]);
mon[x]+=ned[i]*mon[vis[i]];
}
lim[x]=min(lim[x],m/mon[x]);
memset(g,-0x3f3f3f3f,sizeof(g));
g[0][0]=0;
for(int l=lim[x];~l;l--){
int cur=0;
for(int i=head[x];i;i=nxt[i]){
++cur;
for(int j=0;j<=m;j++)
for(int k=0;k<=j;k++)
g[cur][j]=max(g[cur][j],g[cur-1][j-k]+f[vis[i]][l*ned[i]][k]);
}
for(int i=0;i<=l;i++)
for(int j=0;j<=m;j++)
f[x][i][j]=max(f[x][i][j],g[cur][j]+val[x]*(l-i));
}
}
inline void backpack(int now){
for(int i=0;i<=m;i++)
for(int j=0;j<=i;j++)
for(int k=0;k<=lim[now];k++)
dp[cnt][i]=max(dp[cnt][i],dp[cnt-1][j]+f[now][k][i-j]);
}
int main(){
n=read();m=read();
for(int i=1;i<=n;i++){
val[i]=read();
c=gc();
if(c=='B') mon[i]=read(),lim[i]=read();
else{
int num=read();
for(int v,need,j=1;j<=num;j++) v=read(),need=read(),add(i,v,need);
}
}
memset(f,-0x3f3f3f3f,sizeof(f));
for(int now=1;now<=n;now++) if(!in[now]) dfs(now),++cnt,backpack(now);
int ans=0;for(int i=0;i<=m;i++) ans=max(ans,dp[cnt][i]);
cout<<ans;
return 0;
}