美文网首页
火车出站题解+卡特兰数用法小结

火车出站题解+卡特兰数用法小结

作者: 九除以三还是三哦 | 来源:发表于2019-06-05 12:36 被阅读0次
    从出栈可能性了解到了卡特兰数,粗劣的做一下小结。时间超限,数组越界什么的总是很烦恼,继续噶油。
    第二次修改,增加了判断出栈序列是否正确的分析。

    大佬总结的很详细,前面一部分是转过来的。[https://www.cnblogs.com/SovietPower/p/7202443.html]

    一.公式

    卡特兰数一般公式

    令h(0)=1,h(1)=1,catalan数满足递推式。h(n) = h(0)h(n-1)+h(1)h(n-2) + ... + h(n-1)h(0) (n>=2)。也就是说,如果能把公式化成上面这种形式的数,就是卡特兰数

    组合公式

      Cn = C(2n,n) / (n+1)

    (化简前 **h(n) = c(2n,n)-c(2n,n+1) (n=0,1,2,...) 证明

    递归公式1

      h(n) = h(n-1)(4n-2) / (n+1)**

    递归公式2

      h(n) = ∑(i=0 to n-1) h(i)h(n-i-1)*

    二.应用

    • 二叉树的计数等,这个有时间整理吧

    三、例题改错

    题目描述:

    铁路进行列车调度时,常把站台设计成栈式结构的站台,试问:
    设有编号为1到n的n辆列车,顺序开入栈式结构的站台,则可能的出栈序列有多少种?

    输入:

    输入包含多组测试数据。每组为一个正整数n(1<=n<=20),表示有n辆列车。

    输出:

    输出可能的出栈序列有多少种。

    原解:

    # include <iostream>
    using namespace std;
    
    int times(int n)
    {
    int i=0;
    long long sum=0;
    if(n==1||n==0) return 1;
    else if(n==2) return 2;
    else  
    {   
         while(i<n/2)
        {
    sum+=times(n-i-1)*times(i);
    i++; 
        }
    if(n%2==0) return 2*sum;
    else return 2*sum+times((n-1)/2)*times((n-1)/2);
    }
    }
    
    int main()
    {
    int n;
    while(cin>>n)
    {
    cout<<times(n)<<endl;
    }
    } 
    
    

    这个使用递推公式2,一层一层往前递推回去再一层一层回来,造成程序比较复杂,在处理n=20的时候就溢出了。

    改进后:

    # include <iostream>
    using namespace std;
    
    int main()
    {
        long long int ca[20]; ca[0]=1;
        for(int i=1;i<=20;i++)
        {
            ca[i]=ca[i-1]*(4*i-2)/(i+1);
        }
        int n;
        while(cin>>n)
        {
            cout<<ca[n]<<endl;
        }
    } 
    

    优化后的算法为从0开始,使用递推公式1,这样简化了许多!


    一、例题分析

    题目

    火车编号为:1~9,且不重复。如:编号分别为“1”、“2”、“3”、“4”、“5”的5个火车顺序进站,那么进站序列为“12345”,全部进站后再顺序出站,则出站序列为“54321”,如果先进1,2,然后2出站,然后1出站,然后再3进站、出站,4进站、出站,5进站、出站,那么出站序列就为21345.

    输入

    int maxNum:进站的火车最大编号
    char* pOutSeq:使用字符串表示火车出站序列

    输出参数(指针指向的内存区域保证有效):

    无。

    返回值:

    Int: 根据输入的进站序列判断,如果输入的出站序列是可能的,返回1,否则返回0;

    分析:
    由于进栈的顺序是由小到大的,所以出栈序列应该满足以下条件:对于序列中的任何一个数其后面所有比它小的数应该是倒序的

    代码

    #include <iostream>
    #include <string.h>
    #include <stack>
    using namespace std;
    
    int JudgeTrainSequence (int maxNum, char *pOutSeq){
        if(pOutSeq == NULL || maxNum <= 0){
            return 0;
        }
        int size = strlen(pOutSeq);
        stack<int> trainSeq;
        
        int index = 1;  //index用来标记推进去几个 
        for(int i = 0;i < size;){
            if(trainSeq.empty() || trainSeq.top() < pOutSeq[i] - '0'){
                trainSeq.push(index);  //如果不符合出栈顺序,那么一定存在某个数其后面所有比它小的数不是倒序的 ,index最终一定会大于len 
                ++index;
            }
            else{
                trainSeq.pop();
                ++i;
            }
        }
        if(!trainSeq.empty()){
            return 0;
        }
        return 1;
    }
    
    int main()
    {
        char s[3];
        while(cin>>s)
        {
            cout<<JudgeTrainSequence(3,s)<<endl;
        } 
        
    }
    

    相关文章

      网友评论

          本文标题:火车出站题解+卡特兰数用法小结

          本文链接:https://www.haomeiwen.com/subject/mkpjxctx.html