1. 程式人生 > >CF9d How many trees?

CF9d How many trees?

技術分享 hide bits gis clas space register code sed

題意:求節點數為n的,高度大於等於h的二叉樹的個數。

題解:

  一開始沒看到二叉樹的限制,,,想了好久。因為數據範圍很小,所以可以考慮一些很暴力的做法。

  有2種DP方式都可以過。

  1,f[i][j]表示節點數為i,高度恰好為j的方案數,那麽$ans = \sum_{i = h}^{i <= n}{f[n][i]}$.

    於是考慮轉移,首先枚舉節點數i,然後枚舉左兒子Size j,順便就可以算出右兒子Size,但是因為先枚舉節點數為i時的高度不方便轉移,所以考慮直接枚舉左兒子高度和右兒子高度,然後直接轉移即可(具體轉移方程看代碼)。

    復雜度$n ^ 4$  

  2,f[i][j]表示節點數為i,高度小於等於j的方案數,那麽$ans = f[n][n] - f[n][h - 1]$.

    考慮轉移,直接枚舉左兒子Size,那麽就可以算出右兒子Size了,然後因為是高度小於等於j的方案數,所以只需要從f[lson][j - 1] * f[rson][j - 1]轉移而來即可。

 

技術分享圖片
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define R register int
 4 #define AC 40
 5 #define LL long long
 6
7 int n, h; 8 LL ans, f[AC][AC];//i個點,高度恰好為j的方案數 9 10 void pre() 11 { 12 scanf("%d%d", &n, &h); 13 } 14 15 void work() 16 { 17 f[0][0] = 1; 18 for(R i = 1; i <= n; i ++)//枚舉點數 19 for(R j = 0; j < i; j ++)//枚舉左子樹Size 20 { 21 int b = i - j - 1
;//右子樹大小 22 for(int l = 0; l <= j; l ++)//枚舉左子樹高度 23 for(int k = 0; k <= b; k ++)//枚舉右子樹高度 24 f[i][max(l, k) + 1] += f[j][l] * f[b][k]; 25 } 26 for(R i = h; i <= n; i ++) ans += f[n][i]; 27 cout << ans << endl; 28 } 29 30 void work2()//f[i][j]表示節點數為i,高度小於等於j的方案數 31 { 32 for(R i = 0; i <= n; i ++) f[0][i] = 1; 33 for(R i = 1; i <= n; i ++)//枚舉高度 34 for(R j = 1; j <= n; j ++)//枚舉節點個數 35 for(R k = 0; k < j; k ++)//枚舉左子樹size 36 f[j][i] += f[k][i - 1] * f[j - k - 1][i - 1]; 37 cout << f[n][n] - f[n][h - 1] << endl; 38 } 39 40 int main() 41 { 42 //freopen("in.in", "r", stdin); 43 pre(); 44 work2(); 45 //fclose(stdin); 46 return 0; 47 }
View Code

   

    

CF9d How many trees?