AcWing 129:火车进栈 ← DFS

【题目来源】
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




 

猜你喜欢

转载自blog.csdn.net/hnjzsyjyj/article/details/132166746