【题目来源】
https://www.acwing.com/problem/content/131/
【题目描述】
这里有 n 列火车将要进站再出站,但是,每列火车只有 1 节,那就是车头。
这 n 列火车按 1 到 n 的顺序从东方左转进站,这个车站是南北方向的,它虽然无限长,只可惜是一个死胡同,而且站台只有一条股道,火车只能倒着从西方出去,而且每列火车必须进站,先进后出。
也就是说这个火车站其实就相当于一个栈,每次可以让右侧头火车进栈,或者让栈顶火车出站。
车站示意如图:
出站<—— <——进站
|车|
|站|
|__|
现在请你按《字典序》输出前 20 种可能的出栈方案。
【输入格式】
输入一个整数 n,代表火车数量。
【输出格式】
按照《字典序》输出前 20 种答案,每行一种,不要空格。
【数据范围】
1≤n≤20
【测试样例】
输入样例:
3
输出样例:
123
132
213
231
321
【算法分析】
注意:某些出栈序列不能实现。例如,当 n=3 时,没有 312 这个出栈序列。
此外,YXC 大牛给出此题的分析图如下。图中的 state1 在下文的代码中用 vector<int> v; 模拟,图中的 state2 在下文的代码中用 stack<int> cz; 模拟。
【算法代码】
#include <bits/stdc++.h>
using namespace std;
stack<int> cz;
vector<int> v;
int id=1; //下一次入栈的车号
int cnt=0; //答案组数
int n;
void dfs() {
if(cnt==20) return; //只输出20种
if(v.size()==n) {
for(auto t:v) cout<<t;
cout<<endl;
cnt++;
return;
}
if(!cz.empty()){ //出栈
int tmp=cz.top();
v.push_back(tmp);
cz.pop();
dfs();
cz.push(tmp); //回溯
v.pop_back();
}
if(id<=n){ //入栈
cz.push(id++);
dfs();
cz.pop(); //回溯
id--;
}
}
int main() {
cin>>n;
dfs();
return 0;
}
/*
in:
3
out:
123
132
213
231
321
-----------
in:
4
out:
1234
1243
1324
1342
1432
2134
2143
2314
2341
2431
3214
3241
3421
4321
*/
【参考文献】
https://blog.csdn.net/CEOLucifer/article/details/128634737
https://www.acwing.com/solution/content/50994/
https://blog.csdn.net/qq_56721787/article/details/121570417