题目:
这里有 nn 列火车将要进站再出站,但是,每列火车只有 11 节,那就是车头。
这 nn 列火车按 11 到 nn 的顺序从东方左转进站,这个车站是南北方向的,它虽然无限长,只可惜是一个死胡同,而且站台只有一条股道,火车只能倒着从西方出去,而且每列火车必须进站,先进后出。
也就是说这个火车站其实就相当于一个栈,每次可以让右侧头火车进栈,或者让栈顶火车出站。
输入格式
输入一个整数 nn,代表火车数量。
输出格式
按照《字典序》输出前 2020 种答案,每行一种,不要空格。
数据范围
1≤n≤20
输入样例:
3
输出样例:
123
132
213
231
321
思路:
本质是一个dfs+栈的问题,关键在dfs的遍历顺序:从何开始?到什么结束?
1、一共有三种状态,分别DFS其中两种状态。
- state1:已处理状态,已经出站的火车。
- state2:待处理状态,即未进入车站的火车。
- state3:未处理状态,待进站火车
2、边界:当state1中的元素个数等于n时即完全处理完所有元素。
3、操作
- 出站:将st2的栈顶元素赋给st1。
- 进站:将st3放入st2,st3再走一辆车,st3++。注意保证st3是从1开始。
4、回溯
很多DFS最关键的地方是要回溯,将处理的数组还原,重新从新的起点开始
5、保证按字典序!
我们只需要先处理state2状态,即先出站再进站,就能保证后者大于前者
代码:
#include<iostream>
#include<stack>
#include<vector>
using namespace std;
stack<int> st2;
vector<int> st1;
int st3 = 1;
int n,cnt = 20;
void dfs(){
if(!cnt) return;
if(st1.size() == n){
cnt --;
for(int i = 0 ; i < st1.size() ; i ++){
cout << st1[i];
}
cout << endl;
return;
}
//出站
if(st2.size()){
st1.push_back(st2.top());
st2.pop();
dfs();
//还原现场
st2.push(st1.back());
st1.pop_back();
}
//进站
if(st3 <= n){
st2.push(st3);
st3++;
dfs();
//还原现场
st3--;
st2.pop();
}
}
int main(){
cin >> n;
dfs();
return 0;
}