大家一起来数二叉树吧(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 }