HDU 1100 Trees Made to Order (Catalan数)

#include <iostream>
#include <stdio.h>

using namespace std;
int catalan[19]={    1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862,
                     16796, 58786, 208012, 742900, 2674440, 9694845, 35357670, 129644790, 477638700};
int catalan_sum[19]={1, 2, 4, 9, 23, 65, 197, 626, 2056, 6918,
                     23714, 82500, 290512, 1033412, 3707852, 13402697, 48760367, 178405157, 656043857};
int n,x;
void f(int k,int n)//k是要求的树中的节点数,n是要求的树在k个节点的树的排列中的序号,从1开始
{
    int i;
    if(k<=0)return;
    if(k==1)
    {
        cout << "X";
        return;
    }
    for(i=0;i<=k-1;i++)
    {
        if(n<=catalan[i]*catalan[k-1-i])break;
        n-=catalan[i]*catalan[k-1-i];
    }
    int left = i,right = k-1-i;//计算出左右子树应该有的节点数
    n--;//因为我的序号从1开始,而后面要做整除和取余运算,序号要从0开始才能得到正确结果
    if(left>0)
    {
        cout << "(";
        f(left,n/catalan[right]+1);//做完取整运算恢复序号从1开始
        cout << ")";
    }
    cout << "X";
    if(right>0)
    {
        cout << "(";
        f(right,n%catalan[right]+1);//做完取余运算恢复序号从1开始
        cout << ")";
    }
}
int main()
{
    while(cin >> n)
    {
        if(n==0)break;
        n++;
        for(x=0;n>catalan_sum[x];x++);
        f(x,n-catalan_sum[x-1]);
        cout << endl;
    }
    return 0;
}

思路:这道题目的核心是Catalan数,n个节点的二叉树的所有形态个数就是Catalan数的第n项。

n个节点的二叉树的序列增长服从如下规律:左子树节点数0->n-1,右子树每完成一个catalan[i]个数的变换,左子树的序列数加一。左右子树的关系就像两位数中十位和个位的关系。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值