一、题目链接

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. CF1205题解

    B 最高有\(64\)位,当\(n\le 128\)时,最坏情况形成不了三元环,\(floyed\)暴力做 否则直接输出\(3\) C 题意的\(n\)均为奇数,设\((i,j)\),把\(i+j\) ...

  2. Java IO管道流

    import java.io.IOException; import java.io.PipedInputStream; import java.io.PipedOutputStream; publi ...

  3. Node.js之文件下载

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

  4. Momentum Contrast for Unsupervised Visual Representation Learning (MoCo)

    Momentum Contrast for Unsupervised Visual Representation Learning 一.Methods Previously Proposed 1. E ...

  5. 【转】Python编程: 多个PDF文件合并以及网页上自动下载PDF文件

    1. 多个PDF文件合并1.1 需求描述有时候,我们下载了多个PDF文件, 但希望能把它们合并成一个PDF文件.例如:你下载的数个PDF文件资料或者电子发票,你可以使用python程序合并成一个PDF ...

  6. 前端通用下载文件方法(兼容IE)

    之前在网上看到一个博主写的前端通用的下载文件的方法,个人觉得很实用,所以mark一下,方便以后查阅 源文地址(源文还有上传/下载excel文件方法) 因为项目要求要兼容IE浏览器,所以完善了一下之前博 ...

  7. zz SOLID (面向对象设计)

    SOLID (面向对象设计) 维基百科,自由的百科全书 跳到导航 跳到搜索 在程序设计领域, SOLID(单一功能.开闭原则.里氏替换.接口隔离以及依赖反转)是由罗伯特·C·马丁在21世纪早期[1] ...

  8. Mysql的三种数据类型

    Mysql的三种数据类型 1.数值类型 2.日期和时间类型 3.字符串类型 00x1 [数值类型] 00x2 [日期和时间类型] 00x3 [字符串类型]

  9. Spring cloud微服务安全实战-5-9实现基于session的SSO(Token有效期)

    token的有效期 会出现一种情况session有效期还没到.但是token过期了. 用户登陆着,但是token失效了 没法访问服务了. 刷新令牌要和clientId和ClientSecret一起用, ...

  10. 零基础学Python-第二章 :Python基础语法-06.变量的定义和常用操作

    网络带宽计算器的原理 输出的内容用print 引入变量,在前面写一个变量,是一个有意义的单词.把123这个数值赋值给变量a 下面的代码可读性 要比上面高很多. 变量其他需要掌握的知识点 一般这样是用做 ...