一、题目链接

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 死锁以及死锁的产生

    public class DeadLockSample { public static void main(String[] args) { DeadLock d1 = new DeadLock(tr ...

  2. spaceclaim脚本(线生成面体)

    #新建一个列表,用来保存修剪曲线(PS:修建曲线的意思是开始点和结束点不在一起,圆就不属于修建曲线) #注意和Line,Circle类型等的区别 curves = List[ITrimmedCurve ...

  3. 使用 concurrently 并行地运行多个命令(同时跑前端和后端的服务)

    我现在有一个项目是这样的,前端是用 React 写的,后端是用 Nodejs,目录结构如下: . ├── README.md ├── backend ├── node_modules ├── pack ...

  4. MQ消息机制如何确认消费了消息?

    消息队列如何保证消息能百分百成功被消费 目前常用的消息队列有很多种,如RabbitMQ,ActiveMQ,Kafka...下面以RabbitMQ为例来讲如何保证消息队列中的信息能百分百被消费掉. 其中 ...

  5. vim 外部粘贴代码,如何保持原格式,而不持续缩进

    主要内容:使用“:set paste” 来实现vim 按照源文件格式复制 在vim 使用中偶尔要复制外部代码,常常出现不停缩进的问题: 怎么避免此种情况出现呢 可以在命令模式中使用“:set past ...

  6. (转)Darknet模型与Tensorflow模型相互转换

    目前darknet框架下的模型训练都是在C环境下训练的,难免较为晦涩,如果能将模型转换到Tensorflow环境下完成模型的训练,在将训练好的权重转为Darknet可以识别的权重部署到实际应用中.这样 ...

  7. flutter 打开应用的闪屏动画

    import 'package:flutter/material.dart'; import 'package:flutter_app/pages/SplashScreen.dart'; void m ...

  8. weui 可移动悬浮按钮

    @CHARSET "UTF-8"; /** 右下角跳转按钮 跳转到列表 */ #list_note_icon { position: fixed; bottom: 10%; rig ...

  9. win10网上邻居看不到别的共享电脑怎么样办

    https://jingyan.baidu.com/article/4853e1e5b714aa1909f72600.html

  10. 将PCM格式存储成WAV格式文件

    将PCM格式存储成WAV格式文件 WAV比PCM多44个字节(在文件头位置多) 摘自:https://blog.csdn.net/u012173922/article/details/78849076 ...