bzoj1017: [JSOI2008]魔兽地图DotR
树形dp。
好坑的dp。不会。
f[i][j][k]表示第i件装备和它的基础装备一共花费j个金币且向上提供j个装备时能取得的最大的力量值。
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn = 100 + 10; const int maxm = 2000 + 10; int g[maxn],v[maxm],next[maxm],eid; int fa[maxn]; int f[maxn][maxn][maxm],tmp[maxm]; int lim[maxn],a[maxn],c[maxn],r[maxn]; int n,m,res; void addedge(int a,int b) { v[eid]=b; next[eid]=g[a]; g[a]=eid++; fa[b]=a; } bool update(int &x,const int &y) { if(y>x) {x=y; return 1;} return 0; } void solve(int u) { if(g[u]==-1) { lim[u]=min(lim[u],m/c[u]); for(int i=0;i<=lim[u];i++) for(int j=i;j<=lim[u];j++) if(update(f[u][i][j*c[u]],(j-i)*a[u])) update(res,f[u][i][j*c[u]]); return; } lim[u]=maxm; for(int i=g[u];~i;i=next[i]) { solve(v[i]); lim[u]=min(lim[u],lim[v[i]]/r[v[i]]); } for(int i=0;i<=lim[u];i++) f[u][i][0]=0; for(int i=g[u];~i;i=next[i]) for(int j=0;j<=lim[u];j++) { for(int k=0;k<maxm;k++) tmp[k]=f[u][j][k]; memset(f[u][j],-1,sizeof(f[u][j])); for(int k=0;k<=m;k++) for(int l=0;l<=k;l++) if(tmp[k-l]!=-1 && f[v[i]][j*r[v[i]]][l]!=-1) if(update(f[u][j][k],tmp[k-l]+f[v[i]][j*r[v[i]]][l])) update(res,f[u][j][k]); } for(int i=1;i<=lim[u];i++) for(int j=0;j<i;j++) for(int k=0;k<=m;k++) if(f[u][i][k]!=-1) if(update(f[u][j][k],(i-j)*a[u]+f[u][i][k])) update(res,f[u][j][k]); } char op[10]; int main() { memset(g,-1,sizeof(g)); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d%s",&a[i],op); if(op[0]=='B') { scanf("%d%d",&c[i],&lim[i]); } else { int t; scanf("%d",&t); for(int j=1,k;j<=t;j++) { scanf("%d",&k); addedge(i,k); scanf("%d",&r[k]); } } } memset(f,-1,sizeof(f)); for(int i=1;i<=n;i++) if(!fa[i]) solve(i); printf("%d\n",res); return 0; }