火车进栈

背景
话说这是NOI夏or冬令营中的水题......
做题前明确的是,这题当然<>n皇后/全排列


这里有n列火车将要进站再出站……
但是,每列火车只有1节---那就是车头……
描述
有n列火车按1到n的顺序从东方左转进站,这个车站是南北方向的,它虽然无限长,
只可惜是一个死胡同,而且站台只有一条轨道,
火车只能倒着从西方出去,而且每列火车必须进站,先进后出。
(某生:不就是个栈吗?每次可以让右侧头火车进栈,或者让栈顶火车出站?
占卜哥:闭嘴!)
就像这样:
  出站<——-    <——进站
            |车|
            |站|
            |__|
现在请你按《字典序》输出前20种可能的出栈方案。
注意:这题当然不等于全排列!!!
输入格式
一个数n N<=20 数据保证不会TLE所以千万不要halt
输出格式
《字典序》输出前20种答案,每行一种,不要空格
测试样例
输入
3
输出
123 
132 
213 
231 
321




输入
5
输出
12345
12354
12435
12453
12543
13245
13254
13425
13452
13542
14325
14352
14532
15432
21345
21354
21435
21453
21543
23145
输入


8
输出
12345678
12345687
12345768
12345786
12345876
12346578
12346587
12346758
12346785
12346875
12347658
12347685
12347865
12348765
12354678
12354687
12354768
12354786
12354876
12356478
输入


13
输出
12345678910111213
12345678910111312
12345678910121113
12345678910121311
12345678910131211
12345678911101213
12345678911101312
12345678911121013
12345678911121310
12345678911131210
12345678912111013
12345678912111310
12345678912131110
12345678913121110
12345678109111213
12345678109111312
12345678109121113
12345678109121311
12345678109131211
12345678101191213
输入
16
输出
12345678910111213141516
12345678910111213141615
12345678910111213151416
12345678910111213151614
12345678910111213161514
12345678910111214131516
12345678910111214131615
12345678910111214151316
12345678910111214151613
12345678910111214161513
12345678910111215141316
12345678910111215141613
12345678910111215161413
12345678910111216151413
12345678910111312141516
12345678910111312141615
12345678910111312151416
12345678910111312151614
12345678910111312161514

12345678910111314121516

//(模拟)栈,全排列(dfs)

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<stack>
using namespace std;
int n,num=0,a[25],book[25];
int suit()
{
vector<int>vt;
stack<int>st;
int i,j=0;
for(i=1;i<=n;i++)// i代表了火车入栈的顺序
{
//上来先比较当前要入栈的元素和全排列的是否相同
if(i==a[j])//若相同,则该元素入栈后又要立即出栈,所以不必入栈了,存入一个数组vt

{
vt.push_back(i);
j++;
}
else
st.push(i);//若不同,则入栈
while(!st.empty()&&a[j]==st.top()) // 若判断完了a[j],j++,则a[j]变成了下一个元素,因为变完了的
a[j]可能和栈顶元素相等,需要判断是否和此时的栈顶元素是否相等,若相等则出栈,并且存入vt数组,(当时做题的时候把while循环写在了for循环之外)否则可能当i全入栈后也没有找到与a[j]相等的,这样就会错判该顺序不,满足题意。

{
vt.push_back(a[j]);
st.pop();
j++;

}
for(i=0;i<n;i++)
{
if(vt[i]!=a[i])// 最后比较模拟的出栈顺序是否和全排列的结果一样,若一样则满足题意

return 0;
}
return 1;
}
void dfs(int step)//深搜找出全排列结果,
int i,j;
if(step==n&&num<20)

{
if(suit())//
再判断是否满足出栈顺序
{

{
num++;
for(i=0;i<n;i++)
printf("%d",a[i]);
printf("\n"); 
}
return;
}
for(i=1;i<=n;i++)
{
if(book[i]==0)
{
a[step]=i;
book[i]=1;
dfs(step+1);

// if(num>=20)

// return ;
a[step]=0;
book[i]=0;
}
}
return;
}
int main()
{
    scanf("%d",&n);
memset(book,0,sizeof(book));

// memset(a,0,sizeof(a));
dfs(0);
return 0;
 } 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值