问题描述:
在一个列车调度站中,1 条轨道连接到1 条侧轨处,形成1 个铁路转轨栈,如下图所示。 其中左边轨道为车皮入口,右边轨道为出口,编号为1,2,…,n 的n 个车皮从入口依次进 入转轨栈,由调度室安排车皮进出栈次序,并对车皮按其出栈次序重新编序a1, a2,., an 。
思路:
- 生成全排列,检验是否为出栈序列
虽然逻辑简单,但复杂度太高 O ( n ! ∗ n ) O(n!*n) O(n!∗n)。
- 对调度站进行模拟
不难发现,调度站是一个栈的结构,即LIFO。对于调度栈每次有如下几种操作:
- 当还有为入站的车时,拉一辆未入进站的车入栈
- 将站内的一辆车出栈
发现只有未入栈的车没有了,序列就以及定型了,就可以输出。
根据上述逻辑,可以写出如下算法:
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn = (int)1e5+5;
#define repU(i, a, b) for (int i = a; i <= b; i++)
#define repD(i, a, b) for (int i = a; i >= b; i--)
int n;
int stk[maxn], top = -1;
int que[maxn], tail = 0;
//对于栈每次有两次操作 push pop
int dfs (int idx) {
if (idx == n) {
repU(i, 0, tail-1) printf("%d ", que[i]);
repD(i, top, 0) printf("%d ", stk[i]);
putchar('\n');
return 1;
}
int cnt = 0;
if (top != -1) { //pop
que[tail++] = stk[top--];
cnt += dfs(idx);
stk[++top] = que[--tail];
/* 注意区别
top++;
tail--;
*/
}
stk[++top] = idx+1;
cnt += dfs(idx+1);
top--;
return cnt;
}
int main() {
while (scanf("%d", &n)) {
printf("count = %d\n", dfs(0));
system("pause");
}
return 0;
}