《算法競賽入門經典》6.1.2 例題:火車站中轉站車廂重排問題。核心考察棧(LIFO)特性在實際調度中的應用。
target[1..n] 從 B 方向駛出。A → C(入棧)、C → B(出棧)。車廂一旦進 C 不能回 A,進 B 不能回 C。維護三個指標:
A:下一個待從 A 進站車廂編號(初始 1)。B:下一個待輸出到 B 的目標序列索引(初始 1)。stack[top]:中轉站 C,top 為棧頂指針(0 表空)。循環直到 B > n(全輸出成功)或無法操作:
A == target[B]:車廂直通 A→C→B,A++、B++。stack[top] == target[B]:棧頂車廂出站,top--、B++。A <= n:將 A 入棧 stack[++top] = A++。#include <stdio.h>
#define MAXN 1010
int n, target[MAXN];
int main() {
while (scanf("%d", &n) == 1) {
int stack[MAXN], top = 0;
int A = 1, B = 1;
for (int i = 1; i <= n; i++) scanf("%d", &target[i]);
int ok = 1;
while (B <= n) {
if (A == target[B]) { A++; B++; }
else if (top && stack[top] == target[B]) { top--; B++; }
else if (A <= n) { stack[++top] = A++; }
else { ok = 0; break; }
}
printf("%s\n", ok ? "Yes" : "No");
}
return 0;
}
#include <cstdio>
#include <stack>
using namespace std;
#define MAXN 1010
int n, target[MAXN];
int main() {
while (scanf("%d", &n) == 1) {
stack<int> s;
int A = 1, B = 1;
for (int i = 1; i <= n; i++) scanf("%d", &target[i]);
int ok = 1;
while (B <= n) {
if (A == target[B]) { A++; B++; }
else if (!s.empty() && s.top() == target[B]) { s.pop(); B++; }
else if (A <= n) { s.push(A++); }
else { ok = 0; break; }
}
printf("%s\n", ok ? "Yes" : "No");
}
return 0;
}
top 指針。target[1] 為首個目標,stack[1] 為棧底,top=0 為空。A 只增不減,B 只增不減,top 先增後減,單調性保證 O(n) 時間複雜度。