BSG白山极客挑战赛-AVL树


                                                                    AVL树的种类

平衡二叉树(AVL树),是指左右子树高度差至多为1的二叉树,并且该树的左右两个子树也均为AVL树。 现在问题来了,给定AVL树的节点个数n,求有多少种形态的AVL树恰好有n个节点。

Input
<span style="font-size: 14px;">一行,包含一个整数n。 (0 < n <= 2000)</span>
<span style="font-size: 14px;">
</span>
Output
<span style="font-size: 14px;">一行表示结果,由于结果巨大,输出它对1000000007取余数的结果。</span>
<span style="font-size: 14px;">
</span>
Input示例
<span style="font-size: 14px;">10</span>
Output示例
<span style="font-size: 14px;">60</span>

题意:如题。

题目链接:AVL树

解题思路:

首先题目限制是2000个结点,由二叉树的性质可知,最多也只能有20层(20层,2048个结点),所以可以考虑暴力!

然后一棵n个结点的AVL树,其左右两棵子树,也是AVL树,并且总结点数为n-1,而且层次差不能超过1,所以两棵子树也就是两种情况(层次差为0,层次差为1)。

dp[i][j]表示高度为i,结点数为j的所有AVL树的形态数。

就有状态转移方程:

                              dp[i][j]=dp[i-1][k]*dp[i-1][j-k-1]+ dp[i-1][k]*dp[i-2][j-k-1]*2

注意到左右子树层次不同时是可以交换左右子树的,但层次相同的时候循环k其实已经把左右对称的情况考虑了。

总结:

DP的训练还是太少太少了,竟然想到了DP,却不知道怎么列方程!!!不过也再一次见识到了DP的威力。

代码:

#include
#include
#include
#include
#define N 1000000007
using namespace std;

typedef long long ll;
ll dp[20][2005];
int main()
{
    int i,j,k,n;
    while(~scanf("%d",&n)){
        memset(dp,0,sizeof(dp));
        dp[1][1]=dp[0][0]=1;//边界情况
        ll ans=dp[1][n];
        for(i=2;i<20 ;i++  ){ //20层的节点数为2028
            for(j=0;j<=n;j++){ //DP,总结点数位 n
                for(k=0;k

阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭