poj 1095 Trees Made to Order

来源:互联网 发布:新华社新媒体数据库 编辑:程序博客网 时间:2024/05/22 13:47

http://blog.csdn.net/scut_lyq00/article/details/4393598

http://blog.csdn.net/lvlu911/article/details/5425974

题目要求:略

思路:首先,设拥有N个结点的不同形态的有序二叉树有L[N]棵。L[N]即为卡特兰数。那么:

(1).针对这个问题先转换为输入N,求n和k。n表示编号为N的树所拥有的结点数。k表示这棵编号为N的树是拥有结点数为n的树的有序集合的第几棵。我们可以先将Catalan数表打出来:

int L[19]=

{1,1,2,5,14,42,132,429,1430,4862,16796,58786,208012,742900,2674440,9694845,35357670,129644790,477638700};

对于输入的N,可以求出n=min(j|L[0]+L[1]+...+L[j]>=N)。而k=n-L[0]-L[1]- ...-L[n-1]。

鉴于二叉树的固有特性,我可以构造递归函数fun(n,k)。即打印出拥有n个结点树的第k种状态。

(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,s= k- L[0]*L[n-1]- ... L[i-1]*L[n-i]。

(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。

(5).综上所述,fun(n,k)的形式为:

fun(n,k){

   if(1==n)打印X,返回。

   求出 s,i;

   If(i>0){打印(;fun(i, (s-1)/L[n-i-1]+1);打印);}

   打印X;

   If(n-i-1>0) {打印(;fun(n-i-1, (s-1)%L[n-i-1]+1);打印);}

}

#include <iostream>#include <cstdio>using namespace std;const int maxn = 20;int a[maxn], b[maxn];int n;void solve(int num);int main(){a[0] = 1; b[0] = 0; a[1] = 1; b[1] = 1;for(int i = 2; i < maxn; i++){a[i] = 0;for(int j = 0; j < i; j++)a[i] += a[j] * a[i - 1 - j];b[i] = b[i - 1] + a[i];}while(true){scanf("%d", &n);if(0 == n)break;solve(n);printf("\n");}return 0;}void solve(int num){int i, j, t;if(0 == num)return;if(1 == num){printf("X");return;}for(j = 1; j < maxn; j++){if(b[j] >= num)break;}num -= b[j - 1];for(i = 0; i < j; i++){t = a[i] * a[j - 1 - i];if(num > t)num -= t;elsebreak;}if(i != 0){printf("(");solve(b[i - 1] + 1 + (num - 1) / a[j - 1 - i]);printf(")");}printf("X");if(i != j - 1){printf("(");solve(b[j - 2 - i] + 1 + (num - 1) % a[j - 1 - i]); printf(")");}}


原创粉丝点击