12个高矮不同的人,排成两排(catalan数)
问题描述:
12个高矮不同的人,排成两排,每排必须是从矮到高排列,而且第二排比对应的第一排的人高,问排列方式有多少种?
这个笔试题,很YD,因为把某个递归关系隐藏得很深.
问题分析:
我们先把这12个人从低到高排列,然后,选择6个人排在第一排,那么剩下的6个肯定是在第二排.
用0表示对应的人在第一排,用1表示对应的人在第二排,那么含有6个0,6个1的序列,就对应一种方案.
比如000000111111就对应着
第一排:0 1 2 3 4 5
第二排:6 7 8 9 10 11
010101010101就对应着
第一排:0 2 4 6 8 10
第二排:1 3 5 7 9 11
( 012346
5 7891011 000001011111
56891011
)
问题转换为,这样的满足条件的01序列有多少个.
观察1的出现,我们考虑这一个出现能不能放在第二排,显然,在这个1之前出现的那些0,1对应的人
要么是在这个1左边,要么是在这个1前面.而肯定要有一个0的,在这个1前面,统计在这个1之前的0和1的个数.
也就是要求,0的个数大于1的个数.
OK,问题已经解决.
如果把0看成入栈操作,1看成出栈操作,就是说给定6个元素,合法的入栈出栈序列有多少个.
这就是catalan数,这里只是用于栈,等价地描述还有,二叉树的枚举,多边形分成三角形的个数,圆括弧插入公式中的
方法数,其通项是c(2n, n)/(n+1).
在 < <计算机程序设计艺术>>,第三版,Donald E.Knuth著,苏运霖译,第一卷,508页,给出了证明:
问题大意是用S表示入栈,X表示出栈,那么合法的序列有多少个(S的个数为n)
显然有c(2n, n)个含S,X各n个的序列,剩下的是计算不允许的序列数(它包含正确个数的S和X,但是违背其它条件).
在任何不允许的序列中,定出使得X的个数超过S的个数的第一个X的位置.然后在导致并包括这个X的部分序列中,以
S代替所有的X并以X代表所有的S.结果是一个有(n+1)个S和(n-1)个X的序列.反过来,对一垢一种类型的每个序列,我们都能
逆转这个过程,而且找出导致它的前一种类型的不允许序列.例如XXSXSSSXXSSS必然来自SSXSXXXXXSSS.这个对应说明,不允许
的序列的个数是c(2n, n-1),因此an = c(2n, n) - c(2n, n-1).[Comptes Rendus Acad.Sci.105(Paris, 1887), 436~437]
验证:
其中F表示前排,B表示后排,在枚举出前排的人之后,对应的就是后排的人了,然后再验证是不是满足后面的比前面对应的人高的要求.
- C/C++ code
#include <iostream>
using namespace std; int bit_cnt(int n)
{
int result = ;
for (; n; n &= n-, ++result);
return result;
} int main(void)
{
int F[], B[];
int i,j,k,state,ok,ans = ;
for (state = ; state < ( << ); ++state)
{
if (bit_cnt(state) == )
{
i = j = ;
for (int k = ; k < ; ++k)
{
if(state&(<<k))
F[i++] = k;
else
B[j++] = k;
}
ok = ;
for (k = ; k < ; ++k)
{
if (B[k] < F[k])
{
ok = ;
break;
}
}
ans += ok;
}
}
cout << ans << endl;
return ;
}
结果:132
而c(12, 6)/7 = 12*11*10*9*8*7/(7*6*5*4*3*2) = 132
注意:c(2n, n)/(n+1) = c(2n, n) - c(2n, n-1)
估计出题的人也读过 < <计算机程序艺术>>吧.
(另一种解法:
Must be
1 a b
c d e
c could be 2th to 7th ( has to be smaller than d, e... those 5 numbers),
so f(12) = 6 f(10) = 6* 5 f(8) = 30 * 4f(6) = 120*3f(4) = 360*2f(2) = 720
)
)
PS:
另一个很YD的问题:
有编号为1到n(n可以很大,不妨在这里假定可以达到10亿)的若干个格子,从左到右排列.
在某些格子中有一个棋子,不妨设第xi格有棋子(1 <=i <=k, 1 <=k <=n)
每次一个人可以把一个棋子往左移若干步,
但是不能跨越其它棋子,也要保证每个格子至多只有一个棋子.
两个人轮流移动,移动不了的为输,问先手是不是有必胜策略.
12个高矮不同的人,排成两排(catalan数)的更多相关文章
- 12个很少被人知道的CSS事实
之前没有认真的研究过,padding-bottom的值如果是百分比,那么它的实际值是根据父类的宽度来调整的.我还以为是根据这个元素的本身的宽度来定义呢?汗..padding-top/padding-l ...
- 上一篇括号配对让人联想起catalan数,顺便转载一篇归纳的还不错的文章
转载请注明来自souldak,微博:@evagle 怎么样才是合法的组合? 只要每一时刻保证左括号的数目>=右括号的数目即可. 直接递归就行,每次递归加一个括号,左括号只要还有就能加,右括号要保 ...
- MapReduce:将下面的两排数字先按第一排排序,然后再按第二排排序,要求顺序排序
MapReduce:将下面的两排数字先按第一排排序,然后再按第二排排序,要求顺序排序 文件如下: 这个案例主要考察我们对排序的理解,我们可以这样做: 代码如下(由于水平有限,不保证完全正确,如果发现错 ...
- Comet OJ - 2019国庆欢乐赛 C题 两排房子
###题目链接### 题目大意:这里有横着的两排房子,给你每个房子的左端点和右端点.若两排房子中分别有两个房子 x y ,他们在横坐标上有重叠部分(端点重叠也算),则被称为 “对门” 关系. 问你总共 ...
- LintCode 12.带最小值操作的栈(两种方法实现)
题目描述 实现一个带有取最小值min方法的栈,min方法将返回当前栈中的最小值. 你实现的栈将支持push,pop 和 min 操作,所有操作要求都在O(1)时间内完成. 样例 如下操作:push(1 ...
- 使用OC语言编写两个超大数相乘或相加的算法的思路和超大正整数相乘的代码
正文: 在编程中,无论是OC还是C亦或是C++语言,所声明的整数变量都会在内存中占有固定的存储空间,而这些存储空间都是固定的. 比如我们知道的int.long.short.unsigend int.u ...
- 求一个int型整数的两种递减数之和(华为2015笔试题及答案)
给出一个整数(负数使用其绝对值),输出这个整数中的两种递减数(1.最大递减数:2.递减数中各位数之和最大的数)之和. 递减数:一个数字的递减数是指相邻的数位从大到小排列的数字,不包含相邻的数位大小相同 ...
- 求一个int型整数的两种递减数之和(java)--2015华为机试题
题目描述: 给出一个整数(负数使用其绝对值),输出这个整数中的两种递减数(1.最大递减数:2.递减数中各位数之和最大的数)之和. 递减数:一个数字的递减数是指相邻的数位从大到小排列的数字,不包含相邻的 ...
- java实现两个int数交换
普通方法,进阶方法,大神方法 @Test public void test3(){ int m = 5; int n = 12; //要求m和n交换位置 System.out.println(&quo ...
随机推荐
- IE 11 无法访问某些不兼容性视图的解决方法
今天下午部署公司的项目时,用IE 11只能加载到JSP页面的静态元素,其中下拉文本框的信息获取不到, 后来,发现是IE 11不兼容的原因,于是,在菜单条“工具”——“兼容性视图设置”,将不兼容页面的网 ...
- hdu4741
2013年两场网络赛已经过了,之前的现场赛拿了多次铜牌,而这两场网络赛我们都表现得这么水,不由得感慨起来,ACM竞赛生涯就要画上句号了,甚至整个学习生涯中这种纯学术的竞赛都要完了.这两场网络表现得不好 ...
- BZOJ 4321: queue2( dp )
dp(i, j, 1)表示前i个, 有j对是不合法的, i和i-1是在一起的. dp(i, j, 0)表示前i个, 有j对是不合法的, i和i-1不在一起的. 转移我们只需考虑是多了一对不合法的还是少 ...
- Hibernate学习之检索策略
一.类级别的检索策略 类级别可选的检索策略包括立即检索和延迟检索, 默认为延迟检索 –立即检索: 立即加载检索方法指定的对象 –延迟检索: 延迟加载检索方法指定的对象,在使用具体的属性时,再进行加载 ...
- 关于Google指令(别提baidu)
关于google指令 关于google指令 google为我们准备好了的"指令"(directive),可以最大限度帮助我们完成每一次搜索.这些指令其实就是一个个关键字,能让我们从 ...
- Use API to retrieve data from internet
Reference: Working with APIs Many big companies and organizations provide API for us to retrieve dat ...
- printf与scanf的返回值、注意点
printf()的返回值为其输出字符串常量的字符数(注意字符数与字数的区别)注意计数针对所有的打印字符,包括空格和不可见的换行字符(不包括字符串的空字符). scanf()函数返回成功读入的项目的个数 ...
- 专访CEO何朝曦:深信服高速成长的秘诀
在深信服公司深圳总部的办公室里,要迅速找到几位高管的工位远远不如找一位女员工的座位那样容易. 深信服CEO何朝曦先生 公司里虽然女孩很少,但几乎每位女员工的工位上都有一盆绿植.相比之下,从公司CEO何 ...
- HDU 5724 Chess(博弈论)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5724 [题目大意] 给出一个n行,每行有20格的棋盘,棋盘上有一些棋子,每次操作可以选择其中一个棋 ...
- SBT模版
/*Author:WNJXYK*/ #include<cstdio> using namespace std; ; struct SBT{ int left; int right; int ...