











CSP-J/S 2026 第二轮初赛题:旅游
今天我们来解决一道有趣的座位判断题。想象一下:两位同学买了火车票,我们要根据他们的座位号,判断他们是不是坐在同一节车厢、同一排,以及座位之间的关系。
这道题的关键不是计算距离,而是按照题目要求,一层一层地判断。
一、先看懂座位布局
每一排有 5 个座位:
靠窗一侧 过道 另一侧
A B C | D F
注意:
-
A、B、C 在过道左边;
-
D、F 在过道右边;
-
C 和 D 虽然紧挨着过道两侧,但不算相邻座位;
-
同一排的座位号前两位相同,例如 01A、01C 都在第 01 排。
一张座位票由两部分组成:
02 01C
│ │ └─ 座位字母
│ └─── 排号
└─────── 车厢号
例如,02 01C 表示 02 号车厢、01 排、C 座。
二、题目要判断哪四件事?
题目给出两张票:c1 s1 和 c2 s2,要求输出一个由 4 个数字组成的字符串。
从左到右,分别判断:
是否在同一节车厢
是否在同一节车厢、同一排
是否在同一节车厢、同一排,而且在过道同一侧
是否在同一节车厢、同一排、过道同一侧,并且座位相邻
每个条件成立就输出 1,不成立就输出 0。
要特别注意:后面的条件越来越严格。比如,虽然两张票都在过道左侧,但如果不在同一节车厢、同一排,第三位仍然应该是 0。
三、一步一步判断
第一步:判断是否同一节车厢
直接比较车厢号:
bool ans1 = (c1 == c2);
如果相同,ans1 就是 true,输出时会变成 1;否则是 0。
第二步:判断是否同一排
座位字符串的前两位是排号。
例如:
-
01A 的排号是 01
-
01D 的排号也是 01
-
02A 的排号是 02
因此可以比较两个座位字符串的前两位:
bool sameRow = (s1.substr(0, 2) == s2.substr(0, 2));
bool ans2 = ans1 && sameRow;
这里的 && 表示“并且”。所以第二个条件要求:同一节车厢,并且同一排。
第三步:判断是否在过道同一侧
先判断每个座位在过道哪一边:
bool left1 = (s1[2] == 'A' || s1[2] == 'B' || s1[2] == 'C');
bool left2 = (s2[2] == 'A' || s2[2] == 'B' || s2[2] == 'C');
如果座位字母是 A、B、C,就是左侧;否则就是右侧。
然后判断两人是否在同一侧:
bool sameSide = (left1 == left2);
bool ans3 = ans2 && sameSide;
重点: 不能只判断 sameSide。两人即使都在左侧,也必须先满足同一车厢、同一排,第三位才能输出 1。
第四步:判断是否相邻
为了判断座位是否相邻,我们给每一侧的座位编号:
左侧:A=1,B=2,C=3
右侧:D=1,F=2
这样:
-
A 和 B 的编号差是 1,属于相邻;
-
B 和 C 的编号差是 1,属于相邻;
-
D 和 F 的编号差是 1,属于相邻;
-
C 和 D 虽然挨着过道,但属于两侧,不能算相邻。
先写一个函数,把座位字母转换成编号:
int pos(char c) {
if (c == 'A') return 1;
if (c == 'B') return 2;
if (c == 'C') return 3;
if (c == 'D') return 1;
if (c == 'F') return 2;
return 0;
}
再判断编号差是否为 1:
bool adjacent = (abs(pos(s1[2]) – pos(s2[2])) == 1);
bool ans4 = ans3 && adjacent;
注意,最后一位不能只看座位编号差。必须先满足 ans3,也就是同一车厢、同一排、过道同一侧。
四、完整 C++ 程序
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
// 把座位字母转换成这一侧的座位编号
int pos(char c) {
if (c == 'A') return 1;
if (c == 'B') return 2;
if (c == 'C') return 3;
if (c == 'D') return 1;
if (c == 'F') return 2;
return 0;
}
int main() {
string c1, s1, c2, s2;
cin >> c1 >> s1 >> c2 >> s2;
// 第1位:是否在同一节车厢
bool ans1 = (c1 == c2);
// 判断是否同一排
bool sameRow = (s1.substr(0, 2) == s2.substr(0, 2));
// 第2位:同一车厢,并且同一排
bool ans2 = ans1 && sameRow;
// 判断两人是否都在过道左侧
bool left1 = (s1[2] == 'A' || s1[2] == 'B' || s1[2] == 'C');
bool left2 = (s2[2] == 'A' || s2[2] == 'B' || s2[2] == 'C');
// 判断是否在过道同一侧
bool sameSide = (left1 == left2);
// 第3位:同一车厢、同一排、过道同一侧
bool ans3 = ans2 && sameSide;
// 判断座位编号是否相差1
bool adjacent = (abs(pos(s1[2]) – pos(s2[2])) == 1);
// 第4位:前面三个条件都成立,并且座位相邻
bool ans4 = ans3 && adjacent;
cout << ans1 << ans2 << ans3 << ans4 << endl;
return 0;
}
五、用例子检查程序
输入:
02 01C 02 01D
两张票在同一车厢、同一排,但 C 在过道左边,D 在过道右边。
|
同一车厢 |
1 |
都是 02 号车厢 |
|
同一车厢、同一排 |
1 |
都是 01 排 |
|
同一侧 |
0 |
C、D 在过道两侧 |
|
相邻座位 |
0 |
不在同一侧 |
输出:
1100
再看:
02 02B 02 02C
两人同车厢、同一排、同在过道左侧,而且 B、C 相邻,所以输出:
1111
六、这道题最容易错在哪里?
记住这句话:
后面的判断必须建立在前面的条件已经成立的基础上。
尤其是第三位和第四位:
-
第三位不能只判断“是否在过道同一侧”;
-
第四位不能只判断“座位编号差是不是 1”;
-
C 和 D 在过道两侧,不算相邻。
把条件一层一层组合起来,就能避免这些错误。

