[CF509F]Progress Monitoring

题目大意:
  给定一个树的DFS序$b_1,b_2,\ldots,b_n$($b$为$1\sim n$的一个排列且$b_1=1$)。同一个结点的子结点按照结点编号从小到大遍历。问有多少种可能的树的形态?

思路:
  树形DP。
  用$f[l][r]$标示DFS序$b_{l\sim r}$对应多少种树的形态。显然当$l=r$时,$f[l][r]=1$。转移方程为$f[l][r]=\sum_{l<m\le r且b_{m+1}<b_{l+1}}f[l+1][m]\times f[m][r]$。其中$f[l+1][m]$表示$b_{l+1\sim m}$构成树的方案数,$f[m][r]$表示$b_{m+1\sim r}$构成森林的方案数。这是一个$2D/1D$的动态规划,时间复杂度$O(n^3)$。

 1 #include<cstdio>
 2 #include<cctype>
 3 typedef long long int64;
 4 inline int getint() {
 5     register char ch;
 6     while(!isdigit(ch=getchar()));
 7     register int x=ch^'0';
 8     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
 9     return x; 
10 }
11 const int N=501,mod=1e9+7;
12 int b[N],f[N][N];
13 int dfs(const int &l,const int &r) {
14     if(f[l][r]) return f[l][r];
15     if(l==r) return f[l][r]=1;
16     for(register int m=l+1;m<=r;m++) {
17         if(m!=r&&b[l+1]>b[m+1]) continue;
18         (f[l][r]+=(int64)dfs(l+1,m)*dfs(m,r)%mod)%=mod;
19     }
20     return f[l][r];
21 }
22 int main() {
23     const int n=getint();
24     for(register int i=1;i<=n;i++) b[i]=getint();
25     printf("%d\n",dfs(1,n));
26     return 0;
27 }

 

posted @ 2018-05-04 13:07  skylee03  阅读(156)  评论(0编辑  收藏  举报