dp:注意列方程

本文探讨了如何计算具有特定节点数量的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;

}


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值