题目链接:
http://codeforces.com/contest/9/problem/D
题意:
规定一个二叉树,有n个节点,问你深度大于等于h的一共有多少种?这个二叉树满足左儿子比自己小,右儿子比自己大的特性。
题解:
dp。
假设dp[ i ][ j ]表示当前用了 i 个节点,深度度小于等于 j 的方案数。
如果我们直接求深度大于等于h有点难。那么我们就求深度小于等于h的。那么,n个节点高度小于等于n的树的种数,减去,n个节点高度小于等于h-1的种数,这就是我们要求的方案数。
假设节点数n和高度h。那么节点数为n,高度为h的树的种数是怎么得到的?答案是通过两棵子树(高度减一)的种数的乘积得到的。
那么,我们容易得到转移方程:
dp[ n ][ k ] += dp[ i ] [ k - 1] * dp[ n - i - 1 ][ k-1 ] , 其中k是高度,n是节点数,i是左儿子的节点数,n - i - 1 是右儿子的节点数。
显然要枚举高度 k,节点数n,还有左儿子节点数或者右儿子节点数。
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll dp[40][40];
//n个节点高度小于等于n的树的种数-n个节点高度小于等于h-1的种数
int main()
{
int n,h;
cin>>n>>h;
for(int i=1;i<=n;i++)//高度
{
dp[0][i-1] = 1;
for(int j=1;j<=n;j++)//拿n个节点
{
for(int k=0;k<j;k++)//左子树
{
dp[j][i] += dp[k][i-1] * dp[j-k-1][i-1];
}
}
}
cout<<dp[n][n]-dp[n][h-1]<<endl;
return 0;
}