求节点数为n的AVL树的种数

题目

51nod上的一道题,求节点数为n(n<=2000)的不同形态的AVL树有多少种,结果对10^9+7取模。

解法

设dp[i][j]是节点数为i,高度为j的AVL树的数量,则树的左右子树的高度只有3种可能,分别是(j-1,j-1),(j-1,j-2),(j-2,j-1),所以枚举x为左子树的节点数,y为右子树的节点数,h为左子树的节点数,dp[i][j]+=dp[h][x]*dp[i-h-1][y];

代码

#include<cstdio>
#define LL long long
#define mod 1000000007
LL dp[2005][20];
int mi[20],ma[20],dir[5][2]={-1,-1,-1,-2,-2,-1};
int main()
{
	int n,i,j,k,h;
	//ma[i]是高度为i的AVL树的最大节点数
	ma[1]=1;
	for(i=2;i<=20;i++)
		ma[i]=ma[i-1]*2+1;
	//mi[i]是高度为i的AVL树的最小节点数
	mi[1]=1;mi[2]=2;
	for(i=3;i<=20;i++)
		mi[i]=mi[i-1]+mi[i-2]+1;
	dp[1][1]=1;dp[2][2]=2;
	for(i=3;i<=2000;i++)
		for(j=1;j<=20;j++)
		{
			if(i<mi[j]||i>ma[j])
				continue;
			for(k=0;k<3;k++)
			{
				int x=j+dir[k][0];
				int y=j+dir[k][1];
				for(h=mi[x];h<=ma[x];h++)
				{
					if(i-h-1>=1&&mi[y]<=i-h-1&&ma[y]>=i-h-1)
						dp[i][j]=(dp[i][j]+dp[h][x]*dp[i-h-1][y]%mod)%mod;
				}
			}
		}
	while(~scanf("%d",&n))
	{
		LL ans=0;
		for(i=1;i<=20;i++)
			ans=(ans+dp[n][i])%mod;
		printf("%lld\n",ans);
	}
	return 0;
}
    原文作者:AVL树
    原文地址: https://blog.csdn.net/druning/article/details/51469223
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞