出栈序列统计

2.3 出栈序列统计

栈是常用的一种数据结构,有n个元素在栈顶端一侧等待进栈,栈顶端另一侧是出栈序列。你已经知道栈的操作有两种:pushpop,前者是将一个元素进栈,后者是将栈顶元素弹出。现在要使用这两种操作,由一个操作序列可以得到一系列的输出序列。请你编程求出对于给定的n,计算并输出由操作数序列12,…,n,经过一系列操作可能得到的输出序列总数。【问题描述】

【输入】 

就一个数n(①1<=n<=15   ②1n1000)。 

 【输出】

 一个数,即可能输出序列的总数目。

【样例】

stack.in 

3

stack.out

 5

①当n范围较小时,可以用回溯,也可以用递推(这是一个卡特兰数列);

回溯:将题意转化为:给出a、b、c三个栈,a是初状态,b是过渡状态,c是末状态,要把a中的元素最终全放到c中,有两种放法:1、从a中直接放到c中。2、先放到b中,再放到c中(当前元素,有两种选择,放到c中,或者暂时留在b中);

var n:byte;ans:longint;
procedure init;
  begin
    readln(n);
  end;
procedure try(a,b,c,d:longint);//a、b、c三个栈,b表示第几种操作,1-从a中放入b中,2-从a中放入c中,3-从b中放入c中;
  begin
    if c=n then inc(ans);
    if a<n then
      begin
        try(a+1,b+1,c,1);
        try(a+1,b,c+1,2);
      end;
    if (b>0)and(d<>1) then try(a,b-1,c+1,3);
  end;
procedure main;
  begin
    ans:=0;
    try(0,0,0,0);
    writeln(ans);
  end;
begin
 assign(input,'stack.in');reset(input);
 assign(output,'stack.out');rewrite(output);
  init;
  main;
 close(input);close(output);
end.
递推:笔算可知,当n为1,2,3时,答案分别为1,1,5;初步判断为卡特兰数,然后嘛。。。。zy曾经说过,凡是卡特兰数的问题都可以转化为一个模式,不过,我忘了,等哪天问问他,再添上吧。。。。

var n:integer;
    f:array[0..1000]of longint;
procedure init;
  var i:integer;
    begin
      readln(n);
      fillchar(f,sizeof(f),0);
      f[1]:=1;f[2]:=1;f[3]:=5;
    end;
procedure main;
  var i:integer;
    begin
      if n<=3 then
        begin
          writeln(f[n]);
          close(input);close(output);
          halt;
        end;
      for i:=4 to n do f[i]:=(f[i-1]*(4*i-2)) div (i+1);//卡特兰数通项;
      writeln(f[n]);
    end;
begin
 assign(input,'stack.in');reset(input);
 assign(output,'stack.out');rewrite(output);
  init;
  main;
 close(input);close(output);
end.
②当范围较大时,不但要用递推,还得加高精,顺便注意,开数组得开longint的,不然999过不了;

var n,len:integer;
    f:array[0..100000]of longint;
procedure init;
  var i:integer;
    begin
      readln(n);
      fillchar(f,sizeof(f),0);
      f[1]:=1;f[2]:=1;f[3]:=5;
    end;
procedure gcheng(x:integer);
  var i:integer;
    begin
      for i:=1 to len do f[i]:=f[i]*(4*x-2);
      for i:=1 to len do
        if f[i]>=10 then
          begin
            f[i+1]:=f[i+1]+f[i] div 10;
            f[i]:=f[i] mod 10;
          end;
      while f[len+1]<>0 do
        begin
          inc(len);
          f[len+1]:=f[len+1]+f[len] div 10;
          f[len]:=f[len] mod 10;
        end;
    end;
procedure gchu(x:integer);
  var i:integer;
    begin
      for i:=len downto 1 do
        begin
          f[i-1]:=f[i-1]+10*(f[i] mod x);
          f[i]:=f[i] div x;
        end;
      while f[len]=0 do dec(len);
    end;
procedure main;
  var i:integer;
    begin
      if n<=3 then
        begin
          writeln(f[n]);
          close(input);close(output);
          halt;
        end;
      f[1]:=5;f[2]:=0;f[3]:=0;len:=1;
      for i:=4 to n do gcheng(i);
      for i:=5 to n+1 do gchu(i);
      for i:=len downto 1 do write(f[i]);
    end;
begin
 assign(input,'stack.in');reset(input);
 assign(output,'stack.out');rewrite(output);
  init;
  main;
 close(input);close(output);
end.




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值