题目描述:
$\quad$这里有n列火车将要进站再出站,但是,每列火车只有1节,那就是车头。
$\quad$这n列火车按1到n的顺序从东方左转进站,这个车站是南北方向的,它虽然无限长,只可惜是一个死胡同,而且站台只有一条股道,火车只能倒着从西方出去,而且每列火车必须进站,先进后出。
$\quad$也就是说这个火车站其实就相当于一个栈,每次可以让右侧头火车进栈,或者让栈顶火车出站。
输入格式
输入一个整数n,代表火车数量。
输出格式
按照《字典序》输出前20种答案,每行一种,不要空格。
数据范围
$1≤n≤20$
输入样例:
3
输出样例:
123
132
213
231
321
思路1:
$\quad$因为只需要枚举20种情况,因此可以枚举出前n个数的排列组合再依次判断每种组合是否是合法的出栈顺序。判断一种出栈顺序是否合法算法如下:
- 同时使用一个队列q和一个堆栈s来解决该问题,其中,q存储待判断的出栈序列,而s用于模拟序列中每个元素的入栈和出栈过程。
- 这里按照1-n的顺序将每个元素压入栈s:
- 每次压入一个元素,检查栈顶元素与队列头元素是否相同,若相同,s与q同时执行pop操作。
- 若最终栈s为空,说明q里存放的序列是合理的出栈顺序,否则就是不合理的出栈序列。
程序(CPP):
#include <iostream>
#include <vector>
#include <algorithm>
#include <stack>
#include <queue>
using namespace std;
int n;
vector<int> a;
// 判断出栈顺序是否合法
bool check()
{
stack<int> s;
queue<int> q;
for(int i = 0; i < n; i++) q.push(a[i]);
for(int i = 1; i <= n; i++)
{
s.push(i);
while(!s.empty() && s.top()==q.front()) s.pop(), q.pop();
}
if(s.size()==0) return true;
else return false;
}
int main()
{
cin >> n;
for(int i = 1; i <= n; i++)
a.push_back(i);
int cnt = 0;
do
{
if(check())
{
for(int i = 0; i < n; i++) cout << a[i];
cout << endl;
cnt++;
if(cnt==20) break;
}
}while(next_permutation(a.begin(), a.end()));
return 0;
}
牛逼,感谢分享思路
🐂a
大佬厉害鸭!
42题的感觉
这个思路也不错!