大家一起来数二叉树吧(DP)

链接:https://ac.nowcoder.com/acm/problem/13593
来源:牛客网

题目描述

某一天,Zzq正在上数据结构课。老师在讲台上面讲着二叉树,zzq在下面发着呆。
突然zzq想到一个问题:对于一个n个节点,m个叶子的二叉树,有多少种形态呐?你能告诉他吗?
对于第一组样例的解释


输入描述:

每一组输入一行,两个正整数n,m(n<=50)意义如题目

输出描述:

每一行输出一个数,表示相应询问的答案取模1000000007

具体思路:

O(n^4)枚举,dp[i][j]=sigma(dp[x][y]*dp[i-1-x][j-y]);

dp[i][j]表示当前二叉树有i个节点j个叶子节点的方案数,然后枚举左子树,dp[x][y]左子树有x个节点y个叶子节点的方案数。

没注意是二叉树,如果是二叉树的话,就按照左子树和右子树的方法去枚举了。一开始想的是固定上面的节点,然后这棵树的叶子节点是固定的,这样的话,剩下的点就可以随机组合了(打那是没想出来应该怎么组合)

AC代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 # define ll long long
 4 # define LL_inf (1ll<<60)
 5 # define inf 0x3f3f3f3f3
 6 const int maxn = 5e5+100;
 7 const int mod = 1e9+7;
 8 ll dp[55][55];
 9 void init()
10 {
11     dp[0][0]=1;
12     dp[1][1]=1;
13     for(int i=1; i<=50; i++)
14     {
15         for(int j=1; j<=i-1; j++)
16         {
17             for(int x=0; x<=i-1;x++)
18             {
19                 for(int y=0; y<=x; y++)
20                 {
21                     if(i-1-x<0||j-y<0)
22                         continue;
23                     dp[i][j]=(dp[i][j]+(dp[x][y]%mod)*(dp[i-1-x][j-y]%mod)%mod);// 注意这里是累加
24                     dp[i][j]%=mod;
25                 }
26             }
27         }
28     }
29 }
30 int main()
31 {
32     int n,m;
33     init();
34     while(~scanf("%d %d",&n,&m))
35     {
36         printf("%lld\n",dp[n][m]);
37     }
38     return 0;
39 }

猜你喜欢

转载自www.cnblogs.com/letlifestop/p/11005725.html