12个高矮不同的人,排成两排(catalan数)

摘要:
问题描述:12个身高不同的人排成两排,每排必须从矮到高排列,第二排比相应的第一排高。有多少种安排?

问题描述: 
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

  012347

  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 = 0;
    for (; n; n &= n-1, ++result);
    return result;
}

int main(void)
{
    int F[6], B[6];
    int i,j,k,state,ok,ans = 0;
    for (state = 0; state < (1 << 12); ++state)
    {
        if (bit_cnt(state) == 6)
        {
            i = j = 0;
            for (int k = 0; k < 12; ++k)
            {
                if(state&(1<<k))
                    F[i++] = k;
                else
                    B[j++] = k;
            }
            ok = 1;
            for (k = 0; k < 6; ++k)
            {
                if (B[k] < F[k])
                {
                    ok = 0;
                    break;
                }
            }
            ans += ok;
        }
    }
    cout << ans << endl;
    return 0;
}

结果: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数)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇asp.net简单实现利用HttpModule实现防sql注入【PHP】你使用过redis做异步队列么,是怎么用的?有什么缺点?下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

随便看看

微信小程序----返回上一页刷新或当前页刷新

1.Reload()方法刷新当前页面;2.replace()方法刷新当前页面;3.页面自动刷新当前页面;实现js刷新当前页面的三种方法使用微信小程序--返回上一页刷新或当前页面刷新1.在实现效果之前,您需要了解微信小应用程序的页面生命周期。如果你不太清楚,你可以看到微信小程序——页面生命周期;2.我们可以知道微信小程序页面由五个循环组成:onLoad、onR...

从零开始制作Galgame——我的Ren'py学习笔记(一)

然后点击“启动工程”点击“开始游戏”效果应该是这样的好了,现在你就制作出了属于自己的第一个游戏角色在一般的Galgame中,不是所有话都是“旁白”说的,一个完整的游戏里面应该有主角那么,怎么在ren'py中定义角色呢我们把刚才的代码更改一下definel=Characterlabelstart:l"HelloWorld!...

ABB机器人功能程序(FUNC)

功能程序的应用范围非常广泛。熟练的人员可以根据不同的需求创建相应的功能程序。函数程序的固定格式是FUNC,返回结束。在ABB的学习中,许多学生对功能程序几乎一无所知,即使他们真的在使用它。在学习ABB的过程中,我遇到了几个用例,所以我总结了它们以加深我的理解。...

flutter Radio单选框

单选框,允许用户从一组中选择一个选项。...

Navicat数据存放位置和备份数据库路径设置

navicat数据库存储在哪里?有了这样的问题,让我们来解决这个问题。默认情况下安装Navicat,默认情况下也安装MySQL,数据库存储在默认用户的目录中。选择安装目录时,还可以选择数据的位置。很多人此时只是设置了MySQL的安装位置。...

JRebel激活服务搭建

前言因为平时的开发工具是使用IntelliJIDEA,所以热部署项目代码的时候,使用的Jrebel。因为Jrebel是收费的,所以以前用的时候都是在网上找破解方法,在网上找到的办法是输入一个在线激活服务,来进行激活。由于简单方便就一直这样用的,今天早上打开IDEA后发现,Jrebel激活失效了。JRebel很好用,也是离不开大家的支持,所以如果条件允许的话,...