zoukankan      html  css  js  c++  java
  • POJ 1095

    #include <iostream>
    #define MAXN 20
    using namespace std;
    __int64 cat[MAXN];
    int sum;
    void give_catalan();
    void dfs(int node,int num);
    int main()
    {
        //freopen("acm.acm","r",stdin);
        give_catalan();
        int n;
        int i;
        int sum;
        while(cin>>n,n)
        {
            sum = 0;
            for(i = 1; sum < n; ++ i)
            {
                sum += cat[i];
            }
            -- i;
            sum -= cat[i];
            dfs(i,n-sum);
            cout<<endl;
        }
    }
    
    void dfs(int node,int num)
    {
        if(node == 1)
        {
            cout<<'X';
            return;
        }
        int i;
        int j;
        int sum = 0;
        for(i = 0; sum < num; ++i)
        {
            sum += cat[i]*cat[node-i-1];
        }
        -- i;
        sum -= cat[i]*cat[node-i-1];
        num -= sum;
        if(i > 0)
        {
            cout<<"(";
            dfs(i,(num-1)/cat[node-i-1]+1);
            cout<<")";
        }
        cout<<'X';
        if(node-1-i > 0)
        {
            cout<<"(";
            dfs(node-1-i,(num-1)% cat[node-i-1]+1);
            cout<<")";
        }
    }
    void give_catalan()
    {
        int i;
        int j;
        cat[0] = 1;
        cat[1] = 1;
        for(i = 2; i < 20; ++ i)
        {
            cat[i] = 2*(2*(i-1)+1)*cat[i-1]/(i+1);
        //    printf("%d
    ",cat[i]);
        }
    }
    /*
    定理:n个结点能形成的二叉树总数为 卡特兰数 C(2n,n)/(n+1) 或者由递推公式Ci+1=2*(2*i+1) /(i+2)*Ci 
      for(i=2;i<20;i++) 
        {        
            a[i]=2*(2*(i-1)+1)*a[i-1]/(i+1) ;//卡特兰数递推公式
            b[i]=b[i-1]+a[i];   
        }   
        
      (2).继续转化问题,这棵树的左子树和右子树各有结点数多少?设这棵树左子树的结点数为i,右子树的结点数为n-i-1,
      那么这棵树是又左子树的结点数为i,右子树的结点数为n-i-1的形态的第几种(设为第s种)?可以知道当1<=k<=L[0]*L[n-1]时,
      左子树结点树为0,右子树结点数为n-1,s=k;L[0]*L[n-1]+1<=k<=L[1]*L[n-2]时,,左子树结点树为1,
      右子树结点数为n-2,s=k- L[0]*L[n-1] ;...当L[i-1]*L[n-i]+1<= L[i]*L[n-i+1]时,左子树结点树为i,
      右子树结点数为n-i-1,            。
    
    (3).继续想象s增长的过程即为树形态不断发生变化的过程。那么首先是右子树在发生变化,从1到L[n-i-1]。
    继续增长,右子树的形态复位为1,而左子树的形态增加1.因此右子树相当于秒针,左子树相当于分针。
    对于s,该树的左子树编号为(s-1)/L[n-i-1]+1,右子树编号为(s-1)% L[n-i-1]+1。
    
    (4).fun(n,k)的递归终止条件很容易知道,为n==1。此时树的形态只有一种,所以直接打印X。
    */

    关注我的公众号,当然,如果你对Java, Scala, Python等技术经验,以及编程日记,感兴趣的话。 

    技术网站地址: vmfor.com

  • 相关阅读:
    C# 进程间通信之二传递复杂数据类型(转)
    c# 进程间的通信实现之一简单字符串收发
    WinRAR压缩操作帮助类
    软件推荐:扫码格式检测系统
    C#位操作(转)
    浅析c#内存泄漏
    常用SQL语句
    linux下网站搭建
    VS中的活动debug和活动cpu
    让程序员跳槽的非钱原因
  • 原文地址:https://www.cnblogs.com/gavinsp/p/4563275.html
Copyright © 2011-2022 走看看