• 卡特兰数


    卡特兰数

    优秀博客

    1

    2

    3

    卡特兰数是一种经典的组合数,经常出现在各种计算中,其前几项为 : 1, 2, 5, 14, 42,132, 429, 1430, 4862, 16796,

    如果打表or手模找到如上规律可考虑卡特兰数

    公式1:

    (Catalan(n)=sum_{i=0}^{n-1}{Catalan(i)*Catalan(n-i-1)})

    进出栈问题

    模板

    QUESTION : 一个足够大的栈的进栈序列为1,2,3,⋯,n时有多少个不同的出栈序列?

    f[i]表示i个数的全部可能性。

    f[0] = 1, f[1] = 1; 设 x 为当前出栈序列的最后一个,则x有n种取值

    由于x是最后一个出栈的,所以可以将已经出栈的数分成两部分

    1. 比x小 2.比x大

    比x小的数有x-1个,所以这些数的全部出栈可能为f[x-1]

    比x大的数有n-x个,所以这些数的全部出栈可能为f[n-x]

    这两部分互相影响,所以一个x的取值能够得到的所有可能性为f[x-1] * f[n-x]

    另外,由于x有n个取值,所以

    公式2:

    (ans = f[0]*f[n-1] + f[1]*f[n-2] + ... + f[n-1]*f[0];)

    同理解释公式1 :考虑最后一个出栈的元素,比其先进栈先出栈的元素有i个,则比其后进栈先出栈的元素有n−i−1

    球迷购票问题

    双倍经验

    法1:dp

    必须先有 50 元,才能收 100 元(每收一个 100 就得找出一个 50),所以我们枚举手头 50 元的张数就行了。

    $ dp[ i ][ j ] $表示考虑到了前 i 个人,手里现有 j 张 50 。(0<=j<=i)

    每一个$ dp[ i ][ j ] $可以由上一个拿了 50 或者 100 转移过来。

    拿了 100 就是 $ dp[i-1][j-1] $,(拿了 100 自然就得找出一张 50,所以是 j-1)那拿了 50 就自然是 $ dp[i-1][j+1] $了(手头多了一张 50)

    #include <cstdio>
    #include <iostream>
    using namespace std;
    long long f[5050][50];
    int n;
    int main(){
        scanf("%d",&n);
        f[0][0]=1;
        for(int i=1;i<=n*2;i++)
            for(int j=0;j<=min(i,n);j++){
                if(j-1>=0)f[i][j]+=f[i-1][j-1];
                if(j+1<=i+1)f[i][j]+=f[i-1][j+1];
            }   
        printf("%lld
    ",f[n+n][0]);
        return 0;
    }
    

    法2:

    一个A买票后售票处会积累50元钱,一个B买票需要售票处找零50元钱

    说明在一个B买票前至少需要一个A买过票,那么我们就可以将A看作左括号,B看作右括号

    问题就是要求合法得括号匹配,即Catalan数

    n得范围开long long不会溢出 所以用一个快一些的递推公式

    $ h(n)=h(n−1)∗(4∗n−2)/(n+1) $

    cat[0]=cat[1]=1;
    for(int i=2;i<=n;++i)
    	cat[i]=cat[i-1]*(4*i-2)/(i+1);
    

    方格问题

    在n*n的格子中,只在下三角行走,每次横或竖走一格,有多少中走法?

    其实向右走相当于进栈,向左走相当于出栈,本质就是n个数出栈次序的问题,所以答案就是卡特兰数。

    二叉搜索树问题

    **QUESTION ** 有n个结点,问总共能构成几种不同的二叉树

    如果采用中序遍历的话,根结点第k个被访问到,则根结点的左子树有k-1个点、根结点的右指数有n-k个点。k的取值范围为1到n,公式1显然可推

    **QUESTION ** 有n+1个叶子的满二叉树的个数?

    向左记为+1,向右记为−1,按照向左优先的原则,从根节点开始遍历.例如第一个图记为+1,+1,+1,−1,−1,−1,于是由卡特兰数的含义可得满二叉树的个数为Cn

    凸多边形的三角形划分问题

    **QUESTION ** 一个凸的n边形,用直线连接他的两个顶点使之分成多个三角形,每条直线不能相交,问一共有多少种划分方案。

    选择一个基边,显然这是多边形划分完之后某个三角形的一条边。图中我们假设基边是p1pn,我们就可以用p1、pn和另外一个点假设为pi做一个三角形,并将多边形分成三部分,除了中间的三角形之外,一边是i边形,另一边是n-i+1边形。i的取值范围是2到n-1。所以本题的解c(n)=c(2)c(n-1)+c(3)c(n-2)+…c(n-1)c(2)。令t(i)=c(i+2)。则t(i)=t(0)t(i-1)+t(1)t(i-2)…+t(i-1)t(0)

  • 相关阅读:
    使用Session防止表单重复提交
    Session
    使用Cookie进行会话管理
    Java邻接表表示加权有向图,附dijkstra最短路径算法
    web工程中URL地址的推荐写法
    Web工程中各类地址的写法
    HTTP中的重定向和请求转发的区别
    squid代理
    代理服务 squid 隐藏真实ip,也就是透明代理
    docker添加sshd 服务
  • 原文地址:https://www.cnblogs.com/ke-xin/p/13546826.html
Copyright © 2020-2023  润新知