题目链接:
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; }
感想:细心