《算法竞赛入门经典》(第二版) 第 6 章例题 6-2。
题意
这一题的题面较短,其中英文原题也比较容易理解,所以,我们直接分析题意和代码。
本题的题意是右边有一列火车向左开,一列火车可以有很多个车厢,单个车厢来到岔路口的时候,可以选择直接进入 B 轨道,也可以选择在 Station 里面暂存一下,但是 Station 相当于是一个 stack,所以,遵循后进先出的规则。
题目的要求就是,在这样的规则之下,判断给定的序列是否是合法的。
具体我们看几个输入和输出的样例即可。
代码
需要说明一点是,书上给出的代码是有误的,实际提交到 OJ 无法通过。我这里讲解的是我修改之后 AC 的代码。
1// UVa514 Rails
2#include <cstdio>
3#include <stack>
4#include <string>
5
6using namespace std;
7const int MAXN = 1000 + 10;
8
9int n, target[MAXN];
10
11int main() {
12 // 重定向输入数据,省去我们手动输入的繁琐
13 string relativePathToCurrentCFile = "./data/UVa514/input2.txt";
14 // relativePathToCurrentCFile = "./data/UVa210/input3.txt";
15 freopen(string("./ch06" + relativePathToCurrentCFile.substr(1, relativePathToCurrentCFile.size() - 1)).c_str(), "r", stdin);
16
17 while (scanf("%d", &n) == 1) { // 读取 N
18 if (n == 0) {
19 break;
20 }
21 while (true) {
22 scanf("%d", &target[1]); // 读取序列的第一个数
23 if (target[1] == 0) { // 如果是 0,那么,说明当前这个样例结束了
24 printf("\n");
25 break;
26 }
27 for (int i = 2; i <= n; i++) // 继续读入
28 scanf("%d", &target[i]);
29
30 stack<int> s; // 利用 stack 来进行模拟处理
31 int A = 1, B = 1;
32 int ok = 1;
33 while (B <= n) {
34 if (A == target[B]) { // 当前的车厢和 target 在 B 这个位置所要求的车厢是相同的,那么不用经过 station 直接进入左边的轨道即可
35 A++;
36 B++;
37 } else if (!s.empty() && s.top() == target[B]) { // 栈的顶部符合条件
38 s.pop();
39 B++;
40 } else if (A <= n) // 目前没有符号条件的,就入栈
41 s.push(A++);
42 else { // 越界了都没有找到
43 ok = 0;
44 break;
45 }
46 }
47 printf("%s\n", ok ? "Yes" : "No");
48 }
49 }
50
51 return 0;
52}