2.3 出栈序列统计
栈是常用的一种数据结构,有n个元素在栈顶端一侧等待进栈,栈顶端另一侧是出栈序列。你已经知道栈的操作有两种:push和pop,前者是将一个元素进栈,后者是将栈顶元素弹出。现在要使用这两种操作,由一个操作序列可以得到一系列的输出序列。请你编程求出对于给定的n,计算并输出由操作数序列1,2,…,n,经过一系列操作可能得到的输出序列总数。【问题描述】
【输入】
就一个数n(①1<=n<=15 ②1≤n≤1000)。
【输出】
一个数,即可能输出序列的总数目。
【样例】
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.