Problem 44: 火车进栈
Time Limit:1 Ms| Memory Limit:128 MB
Difficulty:2
Description
有n列火车按1到n的顺序从东方左转进站,这个车站是南北方向的,它虽然无限长,
只可惜是一个死胡同,而且站台只有一条轨道,
火车只能倒着从西方出去,而且每列火车必须进站,先进后出。
(某生:不就是个栈吗?每次可以让右侧头火车进栈,或者让栈顶火车出站?
占卜哥:闭嘴!)
就像这样:
出站<——- <——进站
|车|
|站|
|__|
现在请你按《字典序》输出前20种可能的出栈方案。
注意:这题当然不等于全排列!!!
只可惜是一个死胡同,而且站台只有一条轨道,
火车只能倒着从西方出去,而且每列火车必须进站,先进后出。
(某生:不就是个栈吗?每次可以让右侧头火车进栈,或者让栈顶火车出站?
占卜哥:闭嘴!)
就像这样:
出站<——- <——进站
|车|
|站|
|__|
现在请你按《字典序》输出前20种可能的出栈方案。
注意:这题当然不等于全排列!!!
Input
一个数n N<=20
Output
《字典序》输出前20种答案,每行一种,不要空格
Sample Input
3
Sample Output
123
132
213
231
321
132
213
231
321
当进栈序列指针越界时,跳出循环,让剩下的出栈序列和栈顶元素依次比较,若相等,出栈,直到出栈序列越界。
此时,若栈空,说明出栈序列是可能发生的。
#include<stdio.h>
int n, stack[21], top = 0, result[21], record[21], count, a[21];//用stack数组实现栈,用top表示栈顶上一个元素的指针
void pailie(int sum)
{
if(count == 20)
return ;
int i, j;
if(sum == n + 1)//每生成一个全排列就判断一下是不是满足条件
{
for(i = 1; i <=n; i++)
{
a[i] = i;
}
i = j = 1;
top = 0;//一定记得每次开始之前把top置0
while(i <= n)//当进站序列不大于n时
{
if(a[i] == result[j])//先判断进站的和出站的是不是相等,
{
i++;
j++;
}
else if(result[j] == stack[top-1] && top > 0)//再判断出站的是不是和出栈的相同
{
j++;
stack[top-1] = 0;
top--;
}
else//两者都不是,则进站的进栈
{
stack[top] = a[i];
i++;
top++;
}
}
while(j <= n)//栈里的车依次出栈,如果出站序列和出栈序列相等,依次出栈,若出现不等的,跳出循环
{
if(result[j] == stack[top-1])
{
stack[top-1] = 0;
top--;
j++;
}
else
break;
}
if(stack[0] == 0)//若栈空,则依次出栈成功,满足题目条件,若栈非空,说明不可能有这样的出栈顺序
{
for(i = 1; i <= n; i++)
printf("%d", result[i]);
printf("\n");
count++;
}
return ;
}
for(i = 1; i <= n; i++)
{
if(!record[i])
{
result[sum] = i;
record[i] = 1;
pailie(sum + 1);
record[i] = 0;
}
}
}
int main(void)
{
scanf("%d", &n);
pailie(1);
return 0;
}