火车进栈
题目描述
这里有n列火车将要进站再出站……
但是,每列火车只有1节---那就是车头……
描述
有n列火车按1到n的顺序从东方左转进站,这个车站是南北方向的,它虽然无限长,只可惜是一个死胡同,而且站台只有一条股道,火车只能倒着从西方出去,而且每列火车必须进站,先进后出。
(某生:不就是个栈吗?每次可以让右侧头火车进栈,或者让栈顶火车出站?
老师:闭嘴!)
就像这样:
出站<——- <——进站
|车|
|站|
|__|
现在请你按《字典序》输出前20种可能的出栈方案。
但是,每列火车只有1节---那就是车头……
描述
有n列火车按1到n的顺序从东方左转进站,这个车站是南北方向的,它虽然无限长,只可惜是一个死胡同,而且站台只有一条股道,火车只能倒着从西方出去,而且每列火车必须进站,先进后出。
(某生:不就是个栈吗?每次可以让右侧头火车进栈,或者让栈顶火车出站?
老师:闭嘴!)
就像这样:
出站<——- <——进站
|车|
|站|
|__|
现在请你按《字典序》输出前20种可能的出栈方案。
输入
一个整数 n<=20
输出
按照《字典序》输出前20种答案,每行一种,不要空格
样例输入
3
样例输出
123 132 213 231 321
#include <bits/stdc++.h> using namespace std; int n; int ans[25]; int vis[25]; int t=0; int pd() { int maxx; for(int i=0;i<n;i++) { int flag=0; for(int j=i+1;j<n;j++) { if(ans[j]<ans[i]) { if(flag==0) { maxx = ans[j]; flag = 1; } if(maxx<ans[j]) return 0; } } } return 1; } void dfs(int cur) { if(cur==n&&t<=20)//达到出栈20并且输出小于20个 { if(pd()) //如果该序列符合这种入栈出栈的序列 输出 { for(int i=0;i<n;i++) { printf("%d",ans[i]); } printf("\n"); t++; return; } } for(int i=1;i<=n;i++) //制造全排列的数 不需要一直造 当找到了20个之后 直接return { if(!vis[i]) { ans[cur] = i; vis[i] = 1; dfs(cur+1); if(t==20) return; vis[i] = 0; } } } int main() { scanf("%d",&n); dfs(0); }
参考:https://blog.csdn.net/Go_Accepted/article/details/61199971?utm_source=blogxgwz2
模拟进栈出栈的问题,这里因为是有序的,所以每个数字后面比这个数字小的几个数字应该是逆序
例如 14532 符合进栈出栈序列 对于4之后比4小的有2、3必须是逆序32排列
判断代码:
int pd()
{
int maxx;
for(int i=0;i<n;i++) //遍历每一个数之后有没有比自身小的
{
int flag=0;
for(int j=i+1;j<n;j++)
{
if(ans[j]<ans[i])
//有小于自身的数的话 要保证之后比自身数小的数都要比ans[j]小 保证逆序
{
if(flag==0)
{
maxx = ans[j];
flag = 1;
}
if(maxx<ans[j])
return 0;
}
}
}
return 1;
}