一、题目链接

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

二、题目分析

对二叉树的所有形态顺序编号,编号规则是:节点数越多的编号越大;节点数相等,左子树节点数越多的越大;节点数相等,左子树节点数也相等,则依此规则比较右子树。

现给定一个正整数,依题目要求输出对应编号的二叉树形态。

三、求解思路

由题目输出格式要求,很直观地联想到使用深度优先搜索dfs,以当前二叉树对应的编号为条件,依次递归输出左子树和右子树。

 1 int main(void) {
2 int n;
3 unsigned int arr[20] = {0};
4
5 init(arr, 20);
6
7 while (scanf("%d", &n) != EOF && n != 0) {
8 dfs(n, arr, 20);
9 printf("\n");
10 }
11
12 return 0;
13 }

其中arr存储的是不同节点数对应的二叉树形态数,即arr[i]表示有i个节点的二叉树总共有多少种形态。

 1 void dfs(int n, unsigned int *arr, int num) {
2
3 int left, right;
4
5 if (n == 1) {
6 printf("X");
7 return ;
8 }
9
10 getChildren(&left, &right, n, arr, num);
11
12 if (left != 0) {
13 printf("(");
14 dfs(left, arr, num);
15 printf(")");
16 }
17 printf("X");
18 if (right != 0) {
19 printf("(");
20 dfs(right, arr, num);
21 printf(")");
22 }
23 }

通过getChildren得到左右子树对应的编号,然后递归搜索即可。

计算左右子树对应序号的思路:

  1. 计算总节点数nall、左子树节点数nleft和右子树节点数nright;

  2. 在计算总节点数和左子树节点数的同时,刨除所有总节点数小于nall的二叉树形态,刨除所有左子树节点数小于nleft的二叉树形态;

  3. 那么下面如何确定当前左子树是nleft个节点的二叉树中的第几个?当前右子树又是nright个节点的二叉树中的第几个?且看一例

  4. 这里假定左子树有三种形态,分别是1,2,3,右子树有两种形态,分别是a,b。额,其实有哪个节点总数对应三种二叉树形态,这里只是举例子

  5. 由这个小例子可以看出,要想确定左右子树对应的序号,需要依据右子树的形态数 ,对应的就是代码中的div,rem以及下面计算的blablabla

 1 void getChildren(int *left, int *right, int n, unsigned int *arr, int num) {
2
3 int i;
4 int nall, nleft, nright;
5 int div, rem;
6
7 for (i = 1; i < num; i++) {
8 if ((unsigned)n > arr[i]) {
9 n -= arr[i];
10 } else {
11 nall = i;
12 break;
13 }
14 }
15
16 for (i = 0; i < nall; i++) {
17 if ((unsigned)n > arr[i] * arr[nall - i - 1]) {
18 n -= arr[i] * arr[nall - i - 1];
19 } else {
20 nleft = i;
21 break;
22 }
23 }
24 nright = nall - nleft - 1;
25
26 div = n / arr[nright];
27 rem = n % arr[nright];
28
29 *left = *right = 0;
30
31 if (nleft != 0) {
32 for (i = 1; i < nleft; i++) {
33 *left += arr[i];
34 }
35 *left += rem == 0 ? div : div + 1;
36
37 if (nright != 0) {
38 for (i = 1; i < nright; i++) {
39 *right += arr[i];
40 }
41 *right += rem == 0 ? arr[nright] : rem;
42 }
43 }

嗯,差不多就这些了。为什么是arr[20]?怎么计算i个节点对应的二叉树形态数?wiki一下Catalan numbers吧。

附完整代码:

  1 /* http://acm.hdu.edu.cn/showproblem.php?pid=1100 */
2
3 #include <stdio.h>
4
5 void init(unsigned int *arr, int N);
6 void dfs(int n, unsigned int *arr, int num);
7 void getChildren(int *left, int *right, int n, unsigned int *arr, int num);
8
9 int main(void)
10 {
11 int n;
12 unsigned int arr[20] = {0};
13
14 init(arr, 20);
15
16 while (scanf("%d", &n) != EOF && n != 0) {
17 dfs(n, arr, 20);
18 printf("\n");
19 }
20
21 return 0;
22 }
23
24 void init(unsigned int *arr, int N)
25 {
26 int i, j;
27
28 arr[0] = arr[1] = 1;
29 for (i = 2; i < N; i++) {
30 for (j = 0; j < i; j++) {
31 arr[i] += arr[j] * arr[i - j - 1];
32 }
33 }
34 }
35
36 void dfs(int n, unsigned int *arr, int num)
37 {
38 int left, right;
39
40 if (n == 1) {
41 printf("X");
42 return ;
43 }
44
45 getChildren(&left, &right, n, arr, num);
46
47 if (left != 0) {
48 printf("(");
49 dfs(left, arr, num);
50 printf(")");
51 }
52 printf("X");
53 if (right != 0) {
54 printf("(");
55 dfs(right, arr, num);
56 printf(")");
57 }
58 }
59
60 void getChildren(int *left, int *right, int n, unsigned int *arr, int num)
61 {
62 int i;
63 int nall, nleft, nright;
64 int div, rem;
65
66 for (i = 1; i < num; i++) {
67 if ((unsigned)n > arr[i]) {
68 n -= arr[i];
69 } else {
70 nall = i;
71 break;
72 }
73 }
74
75 for (i = 0; i < nall; i++) {
76 if ((unsigned)n > arr[i] * arr[nall - i - 1]) {
77 n -= arr[i] * arr[nall - i - 1];
78 } else {
79 nleft = i;
80 break;
81 }
82 }
83 nright = nall - nleft - 1;
84
85 div = n / arr[nright];
86 rem = n % arr[nright];
87
88 *left = *right = 0;
89
90 if (nleft != 0) {
91 for (i = 1; i < nleft; i++) {
92 *left += arr[i];
93 }
94 *left += rem == 0 ? div : div + 1;
95
96 if (nright != 0) {
97 for (i = 1; i < nright; i++) {
98 *right += arr[i];
99 }
100 *right += rem == 0 ? arr[nright] : rem;
101 }
102 }

HDOJ-1100 Trees made to order的更多相关文章

  1. Trees Made to Order——Catalan数和递归

    Trees Made to Order Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 7155   Accepted: 40 ...

  2. POJ 1095 Trees Made to Order 最详细的解题报告

    题目来源:Trees Made to Order 题目大意:根据下面的规则给一棵二叉树编号: 规则1:如果二叉树为空,则编号为0: 规则2:如果二叉树只有一个节点,则编号为1: 规则3:所有含有m个节 ...

  3. HDU.P1100 Trees Made to Order 解题报告

    http://www.cnblogs.com/keam37/p/3637717.html  keam所有 转载请注明出处 Problem Description We can number binar ...

  4. POJ 1095 Trees Made to Order(卡特兰数列)

    题目链接 中间计算的各种细节.有的细节没处理好,就wa了...主要思路就是根据卡特兰数列的: h(n)= h(0)*h(n-1)+h(1)*h(n-2) + ... + h(n-1)h(0) (n&g ...

  5. poj 1095 Trees Made to Order 卡特兰数

    这题用到了卡特兰数,详情见:http://www.cnblogs.com/jackge/archive/2013/05/19/3086519.html 解体思路详见:http://blog.csdn. ...

  6. poj 1095 Trees Made to Order

    http://poj.org/problem?id=1095 先求出n个节点数的二叉树的形态有多少种.卡特兰数f[n]=f[n-1]*(4*n-2)/(n+1);再递归求. #include < ...

  7. POJ1095 Trees Made to Order(JAVA)

    这题用到了卡特兰数,比较麻烦.关于卡特兰数的基本概念百度一下你就知道. 使用卡特兰数对数组元素进行分组之后,需要具体计算一下要求的是第几组的第几个数,然后向下递归. 首先来看利用卡特兰数分组: 从1开 ...

  8. [Swift]LeetCode894. 所有可能的满二叉树 | All Possible Full Binary Trees

    A full binary tree is a binary tree where each node has exactly 0 or 2 children. Return a list of al ...

  9. [LeetCode] 894. All Possible Full Binary Trees 所有可能的满二叉树

    A full binary tree is a binary tree where each node has exactly 0 or 2 children. Return a list of al ...

随机推荐

  1. Java 学习之路(2)程序基本要素

    编写一个程序,基本要素包括:标识符.关键字.注释.修饰符.块.语句.类和main()方法. 标识符 概念 在Java语言中:标识符是用来给类.对象.方法.变量.接口和自定义数据类型命名的. 标识符组成 ...

  2. zabbix-3.4邮件报警

    1.开启smtp邮件传输协议 会生成一个授权码后面有用 2.卸载旧版的邮件服务 rpm -qa | grep mailx rpm -qa | grep sendmail rpm -qa | grep ...

  3. Node.js之文件下载

    Node.js之文件下载,主要最近解决我的一个需求. 需求描述:如何将腾讯云上传的文件存储到本地某个目录下,如果用js来实现,纯JavaScript没有这样的功能(也许有),正好我这个项目用node. ...

  4. JavaWeb之问题集(1) —— Tomcat启动闪退

    1. 问题描述 环境: System:Windows 10 Professional JDK:1.8.0.212 Tomcat:9.0.22 原本可以正常的启动和关闭,后来突然的就无法使用了,无法启动 ...

  5. Spring boot RSA 文件加密解密

    github项目地址 rsa_demo ##测试 加密D:/hello/test.pdf 文件,生成加密后的文件 testNeedDecode.pdf 对testNeedDecode.pdf 文件进行 ...

  6. DELPHI开发LINUX包

    DELPHI开发LINUX包 我们知道,有了包的存在,开发插件架构的程序,才成为可能 . DELPHI在WINDOWS里面的包的扩展名是.bpl. 在LINUX里面的包的扩展名是.so. 怎样在LIN ...

  7. ORA-39142: incompatible version number 5.1 in dump file

    ORA-39142: incompatible version number 5.1 in dump file http://blog.itpub.net/26664718/viewspace-214 ...

  8. C 套接字

    套接字函数 1 创建套接字──socket() 应用程序在使用套接字前,首先必须拥有一个套接字,系统调用socket()向应用程序提供创建套接字的手段,   其调用格式如下:SOCKET PASCAL ...

  9. Spark(四十八):Spark MetricsSystem信息收集过程分析

    MetricsSystem信息收集过程 参考: <Apache Spark源码走读之21 -- WEB UI和Metrics初始化及数据更新过程分析> <Spark Metrics配 ...

  10. shell获取今天、明天、昨天、n天、周、月、年日期

    1.获取今天日期 $ date -d now +%Y-%m-%d   或者$ date +%F 1    2 2.获取明天日期 $ date -d next-day +%Y-%m-%d$ date - ...