[bzoj1017]: [JSOI2008]魔兽地图DotR
为啥这年头dp的复杂度也变玄学了>_<
一开始想来想去都觉得会TLE。。。最后无力跑去膜黄学长的题解 http://hzwer.com/5198.html
f[i][j][k]表示以i为根的子树中,有j件装备i用于他父亲的合成,共花费k元的最大力量值。。。
具体做法见题解>_<。。。
YY了几个小剪枝(虽然并不是很快)。。一个是先求出当前子树里最多可能花多少钱,这样就不用每次从m开始枚举= =,另一个是,用于合成父亲的装备数显然没必要多于父亲装备最多需要的数目。。
实测,手写max,min函数后速度是原来的一倍多。。。。。去掉所有的inline和register后速度并没有什么改变= =
总的时间复杂度大概是O(100*n*m*m)?大概两百多亿。。。反正没有什么实际意义>_<
珍爱常数远离stl 。。
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 using namespace std; 5 const int inf=1002333333; 6 struct zs{ 7 int too,pre,num; 8 }e[23333];int last[53],tot; 9 int f[53][101][2023],mxnum[53],v[53],cost[53],fa[53],dl[53],mxneed[53],mxcost[53]; 10 int g[2023]; 11 int i,j,k,n,m,a,b,ans; 12 13 int ra;char rx; 14 inline int read(){ 15 rx=getchar(),ra=0; 16 while(rx<'0'||rx>'9')rx=getchar(); 17 while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra; 18 } 19 inline void insert(int a,int b,int num){ 20 e[++tot].too=b,e[tot].num=num,e[tot].pre=last[a],last[a]=tot; 21 } 22 inline int min(int a,int b){return a<b?a:b;} 23 inline int max(int a,int b){return a<b?b:a;} 24 inline void prerun(){ 25 register int i,l,r,now; 26 for(l=r=0,i=1;i<=n;i++)if(!fa[i])dl[++r]=i; 27 while(l<r) 28 for(i=last[now=dl[++l]];i;i=e[i].pre) 29 dl[++r]=e[i].too; 30 for(i=r;i;i--)if(!cost[dl[i]]){ 31 mxnum[dl[i]]=inf; 32 for(j=last[dl[i]];j;j=e[j].pre) 33 cost[dl[i]]+=cost[e[j].too]*e[j].num, 34 mxnum[dl[i]]=min(mxnum[dl[i]],mxnum[e[j].too]/e[j].num); 35 mxnum[dl[i]]=min(mxnum[dl[i]],m/cost[dl[i]]); 36 } 37 for(i=1;i<=r;i++) 38 for(j=last[dl[i]];j;j=e[j].pre) 39 mxneed[e[j].too]=mxnum[dl[i]]*e[j].num; 40 //装备x最多可能有mxneed[x]个用于他爹的合成 41 } 42 void dfs(int x,int fa){ 43 register int i,j,j1,k,to,vx,costx,numto,costto; 44 if(!last[x]){ 45 for(i=0;i<=mxnum[x];i++) 46 for(j=max(0,i-mxneed[x]);j<=i;j++)f[x][i-j][i*cost[x]]=j*v[x]; 47 mxcost[x]=mxnum[x]*cost[x]; 48 return; 49 } 50 51 for(i=last[x];i;i=e[i].pre) 52 dfs(e[i].too,x),mxcost[x]+=mxcost[e[i].too];//mxcost:最多可能花多少钱 53 if(mxcost[x]>m)mxcost[x]=m; 54 for(i=costx=0;i<=mxnum[x];i++,costx+=cost[x]){ 55 memset(g,200,(mxcost[x]+1)<<2),g[0]=0; 56 for(to=e[j1=last[x]].too;j1;to=e[j1=e[j1].pre].too) 57 for(numto=i*e[j1].num,costto=cost[to]*numto,j=mxcost[x]-costx;j;j--) 58 for(k=j;k;k--) g[j]=max(g[j],g[j-k]+f[to][numto][k+costto]); 59 60 for(j=min(i,mxneed[x]),vx=(i-j)*v[x];j>=0;j--,vx+=v[x])//用j个装备x合成 61 for(k=costx,j1=0;k<=mxcost[x];k++,j1++) 62 if(g[j1]+vx>f[x][j][k])f[x][j][k]=g[j1]+vx; 63 } 64 } 65 66 int main(){ 67 n=read(),m=read();char id; 68 for(i=1;i<=n;i++){ 69 v[i]=read(); 70 for(id=getchar();id<'A'||id>'B';id=getchar()); 71 if(id=='B')cost[i]=read(),mxnum[i]=min(read(),m/cost[i]); 72 else for(k=read(),j=1;j<=k;j++)a=read(),insert(i,a,read()),fa[a]=i; 73 } 74 prerun(); 75 for(i=1;i<=n;i++)for(j=0;j<=mxneed[i];j++)memset(f[i][j],200,(m+1)<<2); 76 for(i=1;i<=n;i++)if(!fa[i]){//只有一棵树= = 77 dfs(i,0); 78 for(j=0;j<=m;j++) if(f[i][0][j]>ans)ans=f[i][0][j]; 79 } 80 printf("%d\n",ans); 81 return 0; 82 }