[HDU] 1100 Trees Made to Order catalan数的应用

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=1100

方法:

首先根据输入的n判断出树里有多少个点m,然后设点数小于等于m的数的形态个数为x,则远问题转换成求n个点组成的树中排名第n-x的树的形态

设buildTree(count,order)为建立count的点组成的树中排名order的树。

核心就在该函数里。

先设i是左子树的个数,0<=i<=count-1,而右子树是j=cout-1-i,

依次考查每一个i,考查的时候又依次考查i个点对应的k个形态,直到发现一个形态的排名达到目标排名order。通过模拟可以计算得出左子树有多少个点lcount,形态排名lorder,右子树多少个点rcount,形态排名rorder。然后递归调用buildTree(lcount,lorder)和buildTree(rcount,rorder)来分别构造左右子树。

代码:

#include <iostream>
#include <queue>
#include <iomanip>
using namespace std;
int catalan[18]={1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, 2674440, 9694845, 35357670, 129644790};
int catalanSum[18];
struct Node
{
    Node* left;
    Node* right;
};
Node* createTree(int count,int order)
{
	if(count==0)
		return NULL;
	Node* re = (Node*)malloc(sizeof(Node));
	re->left=NULL;
	re->right=NULL;
	if(count==1)
		return re;
	int sonCount = count-1;
	int t_sortNo=0;
	for(int i=0;i<=sonCount;i++)
	{
		for(int j=1;j<=catalan[i];j++)
		{
			if(t_sortNo+catalan[sonCount-i]>=order)
			{
				re->left = createTree(i,j);
				re->right =  createTree(sonCount-i,order-t_sortNo);
				return re;
			}
			else 
				t_sortNo+=catalan[sonCount-i];
		}
	}
}
void outputTree(Node* root)
{
	if(root->left!=NULL)
	{
		cout<<"(";
		outputTree(root->left);
		cout<<")";
	}
	cout<<"X";
	if(root->right!=NULL)
	{
		cout<<"(";
		outputTree(root->right);
		cout<<")";
	}
}
int main()
{
    int n;
	catalanSum[0]=1;
	for(int i=1;i<18;i++)
		catalanSum[i]=catalanSum[i-1]+catalan[i];
    while(scanf("%d",&n)&& n!=0)
    {
	   n++;
	   int i=0;
       while(catalanSum[i]<n&&i<18)//i<18很重要的条件
		   i++;
	   n-=catalanSum[i-1];
	   outputTree(createTree(i,n));
	   cout<<endl;
    }
    return 0;
}

 感想:细心

posted @ 2013-08-05 19:09  kbyd  阅读(405)  评论(0编辑  收藏  举报