题号:NC13593 链接:https://ac.nowcoder.com/acm/problem/13593 来源:牛客网
题目描述 某一天,Zzq正在上数据结构课。老师在讲台上面讲着二叉树,zzq在下面发着呆。 突然zzq想到一个问题:对于一个n个节点,m个叶子的二叉树,有多少种形态呐?你能告诉他吗? 对于第一组样例的解释
思路: 这是典型的动态规划,状态变量:n个节点,m个叶子决定了数量。
即dp[n][m]代表n个节点,m个叶子的数量
因为是二叉树,要么是左边,要么是右边,也就是说,n个节点除了给根节点外,还是剩下n-1个,这个n-1个节点要么在左边,要么在右边。叶子也是一样,要么在左边,要么在右边。
因此:
dp[n][m] = ∑(dp[k1][k2]*dp[n-1-k1][m-k2]), 其中k1,k2范围为[0,n-1],[0,m]
dp[k1][k2]如果k2>k1,显然这个值为0
附代码:
```// dddd.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string.h>
#include <vector>
using namespace std;
int main() {
int n,m;
long long dp[100][100];
n = 50;
for (int i = 0; i <= n; i++) {
dp[0][i] = 0;
dp[1][i] = 0;
}
dp[0][0] = 1;
dp[1][1] = 1;
for (int i = 2; i <= n; i++) {
for (int j = 0; j <= i; j++) {
dp[i][j] = 0;
for (int k1 = 0; k1 <= i-1; k1++) {
for (int k2 = 0; k2 <= j; k2++) {
dp[i][j] += dp[k1][k2] * dp[i - 1 - k1][j - k2];
dp[i][j] %= 1000000007;
}
}
}
for (int j = i + 1; j <= n; j++) {
dp[i][j] = 0;
}
}
while (scanf("%d%d", &n, &m) > 0) {
cout << dp[n][m] << endl;
}
return 0;
}