[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 }
View Code

 

posted @ 2016-02-12 10:39  czllgzmzl  阅读(724)  评论(0编辑  收藏  举报