[NOIP2003 普及组]栈

题目背景

        栈是计算机中经典的数据结构,简单的说,栈就是限制在一端进行插入删除操作的线性表。

        栈有两种最重要的操作,即 pop(从栈顶弹出一个元素)和 push(将一个元素进栈)。

        栈的重要性不言自明,任何一门数据结构的课程都会介绍栈。宁宁同学在复习栈的基本概念时,想到了一个书上没有讲过的问题,而他自己无法给出答案,所以需要你的帮忙。

题目描述

        宁宁考虑的是这样一个问题:一个操作数序列,1,2,…,n(图示为1到3的情况),栈 A 的深度大于n。

现在可以进行两种操作:

        1.将一个数,从操作数序列的头端移到栈的头端(对应数据结构栈的push操作)

        2.将一个数,从栈的头端移到输出序列的尾端(对应数据结构栈的pop操作)

        使用这两种操作,由一个操作数序列就可以得到一系列的输出序列,下图所示为由 1 2 3 生成序列 2 3 1 的过程。

(原始状态如上图所示)

        你的程序将对给定的n,计算并输出由操作数序列 1,2,…,n 经过操作可能得到的输出序列的总数。

输入

输入文件只含一个整数(1≤n≤18)。

输出

输出文件只有一行,即可能输出序列的总数目。

样例组

输入 3
输出 5

题目来源

NOIP 2003 普及组第三题


题目思路

        这道题目有三种思路。

        第一种:栈模拟

        解法:开一个stack栈,dfs+bfs求出出栈队伍的数量。(在生成全排列的基础上增加一个判断是否合法的BFS函数)

        得分:60分

        代码:

#include<bits/stdc++.h>
using namespace std;
int n,s[60005],f[60005];long long sum=0;
int check()
{
	int h=1,t=1;
    stack<int>p; 
    while(h<=n)
    {
        if(h==s[t])h++,t++;
        else if(p.empty()||p.top()!=s[t])
        {
            p.push(h);
            h++;
        }
        else if(p.top()==s[t])
        {
            p.pop();
            t++;
        }
    }  
    while(!p.empty())
    {
        if(p.top()==s[t])
        {
            p.pop();
            t++;
        }
        else return 0;
    }  
    return 1;
}
void dfs(int d)
{
    //if(sum==20) 
    if(d>n)
    {if(check())  sum++;}
    else
    {
    	for(int i=1;i<=n;i++)
    	{
        	if(!f[i])
        	{
            	f[i]=1;s[d]=i;
            	dfs(d+1);f[i]=0;
        	}
    	}
    }
}
int main()
{
    scanf("%d",&n);
    dfs(1);
    printf("%d",sum);
    return 0;
}

        第二种:生成卡特兰数

        解法:根据Calatan(卡特兰)数的性质,递推一个个生成卡特兰数,直到生成第N个卡特兰数为止。(注意数组要开long long)

        分数:100分

        代码:

#include<bits/stdc++.h>
using namespace std;
long long f[101],n;
int main()
{
	c[0]=c[1]=1;
	cin>>n;
	for(int i=2;i<=n;i++)
		for(int j=0;j<i;j++)	c[i]+=c[j]*c[i-j-1];
	cout<<c[n];
	return 0;
}

        第三种:打表!

        思路:(从网上当来前20个Calatan数)将前20个卡特兰数存入数组C,然后直接输出卡特兰数的第N项就行了。

        分数:100分

        代码:

#include<bits/stdc++.h>
using namespace std;
long long n,c[]={1,1,2,5,14,42,132,429,1430,4862,16796,58786,208012,742900,2674440,9694845,35357670,129644790,477638700,1767263190,6564120420};
int main()
{
	cin>>n;
	cout<<c[n];
	return 0;
}

        这道题目就这么多。 

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值