dp:注意列方程

来源:互联网 发布:centos 修改ssh端口号 编辑:程序博客网 时间:2024/05/16 10:19

AVL树的种类


平衡二叉树(AVL树),是指左右子树高度差至多为1的二叉树,并且该树的左右两个子树也均为AVL树。 现在问题来了,给定AVL树的节点个数n,求有多少种形态的AVL树恰好有n个节点。
Input
一行,包含一个整数n。 (0 < n <= 2000)
Output
一行表示结果,由于结果巨大,输出它对1000000007取余数的结果。
Input示例
10
Output示例
60


n个结点最高为log1.68(n),最低为log2n,dp[i][h] 为i个结点高度为h的个数。

dp[i][j] 可分为三种情况:①左右子树高度相同:dp[j][h-1]*dp[i-1-j][h-1];
                                       ②左右子树高度差一:dp[i][h-1]*dp[i-1-j][h-2];
                                       ③左右子树高度差一:dp[i][h-2]*dp[i-1-j][h-1]   (②③两种情况相同可直接乘二)

需要注意:dp[0][0]和dp[1][1]  后续乘法会用到,所以初始化的时候必须改为1!

n个节点的情况为高度为h1,h2,h3,h4... 因此将结点为n,高度为2-h的所有dp相加。

中间不要忘记 正! 确! 的! 取余
注意 j,h的范围数组下标0 - MAX




#include<iostream>#include<cstring>using namespace std;const int mod = 1000000007;const int MAX_N = 2000;int n;long long dp[MAX_N + 5][25];void solve(){    int h;    int sum = 0;    memset(dp,0,sizeof(dp));    dp[0][0] = 1;    dp[1][1] = 1;    for(int i = 2; i <= n; i++)        for(int j = 0; j < i; j++)            for(h = 2; h <= 20; h++)            {                dp[i][h] += dp[j][h-1] * dp[i-j-1][h-1]%mod;          //开始没写 +                dp[i][h] += 2*dp[j][h-1]*dp[i-j-1][h-2]%mod;                dp[i][h] %= mod;            }    for(int i = 0; i <= h; i++)    {        sum += dp[n][i];        sum %= mod;                         // 这里取余    }    cout<<sum<<endl;}int main(){    cin>>n;    solve();    return 0;}


0 0