卡特兰数及其具体应用举例

卡特兰数介绍

有这样一个经典问题,我有2n个游客去景区旅游,每个游客需要支付50元的费用,但是只有n个游客手里刚好有50元,其余n个游客手里都只有100元,那么问,该如何购票才可以完全找零?首先我们考虑所有的情况,就是一个数列,我们选择其中的n个为50,其余n个为100,则根据排列组合数的定义我们可以得到,这有C(n,2n)种情况,然后我们考虑非法的情况,我们把50假设为+1,100假设为-1,则当我们进行排列的时候,如果前n项的和不为正数就说明50元的数目少于100元了,我们知道一张50元可以对应一张100的找零,所以此时我们就没有办法对这个排列进行处理了。那么,如果我们把这个第n项前面的前n-1项全部取反,我们就会得到一个合法的序列,但是这个时候的话我们选择的100元个数就是n-1了,所以根据映射关系,每一个选取n-1张100元的排列方式一定对应一种非法的排列,所以最终我们的答案是C(n,2n)-C(n-1,2n)((1/n+1)*C(2n,n))。这个就是卡特兰数的一种表示方法和具体应用。

关于卡特兰数可以解决的一些实际问题

1.进出栈问题
2.求满二叉树的个数问题
3.电影购票问题
4.圆内连线问题
5.凸多边形的剖分问题(n+2边形用n-1条对角线切割)

例题

题面

Problem Description
The "Harry Potter and the Goblet of Fire" will be on show in the next few days. As a crazy fan of Harry Potter, you will go to the cinema and have the first sight, won’t you?

Suppose the cinema only has one ticket-office and the price for per-ticket is 50 dollars. The queue for buying the tickets is consisted of m + n persons (m persons each only has the 50-dollar bill and n persons each only has the 100-dollar bill).

Now the problem for you is to calculate the number of different ways of the queue that the buying process won't be stopped from the first person till the last person.
Note: initially the ticket-office has no money.

The buying process will be stopped on the occasion that the ticket-office has no 50-dollar bill but the first person of the queue only has the 100-dollar bill.

Input
The input file contains several test cases. Each test case is made up of two integer numbers: m and n. It is terminated by m = n = 0. Otherwise, m, n <=100.

Output
For each test case, first print the test number (counting from 1) in one line, then output the number of different ways in another line.

Sample Input
3 0
3 1
3 3
0 0

Sample Output
Test #1:
6
Test #2:
18
Test #3:
180

解析

这个题目和上面的引例差不多,首先我们简单判断当n<m的时候,显然无论怎么排列都不会成立的,然后当n>=m的时候,我们可以应用卡特兰数,另外这个题目的话,我们需要用一下java大数。

代码实现

import java.io.*;
import java.util.*;
import java.math.*;
public class hdu1133 {
    public static void main (String []args) {
        Scanner cin = new Scanner(System.in);
        Integer n,m,i,N = 202;
        BigInteger rest=BigInteger.ONE;
        // BigInteger []jac = new BigInteger[N];
    
        Integer sp=0;
        while (cin.hasNext()) {
             sp++;
             m=cin.nextInt();
             n=cin.nextInt();
             rest = BigInteger.ONE;
             for (i=2;i<=n+m;i++) rest=rest.multiply(BigInteger.valueOf(i));
             if (m==0&&n==0) return ;
             if (m<n) rest=BigInteger.valueOf(0);
             else {
                 rest = rest.multiply(BigInteger.valueOf(m-n+1));
                 rest = rest.divide(BigInteger.valueOf(m+1));
             }
             System.out.println("Test #"+sp+":");
             System.out.println(rest);
        }
        cin.close();
     }  
}
原文地址:https://www.cnblogs.com/hhlya/p/13232245.html