1. 括号匹配
时间限制:1秒 内存限制:128M
题目描述
假设表达式中允许包含圆括号和方括号两种括号,其嵌套的顺序随意,如(<>)或[([][])]等为正确的匹配,[(])或(<>或(()))均为错误的匹配
本题的任务是检验一个给定的表达式中的括号是否匹配正确
输入一个只包含圆括号和方括号的字符串,判断字符串中的括号是否匹配,匹配就输出"OK",不匹配就输出"Wrong"
输入描述
一行字符,只含有圆括号和方括号,个数小于255
输出描述
匹配就输出一行文本"OK",不匹配就输出一行文本"Wrong"
样例
输入
bash
[(])
输出
bash
Wrong
解题思路:
【题目分析】
利用数组模拟栈的 "后进先出" 特性,完美契合了 "括号匹配需左括号与最近右括号成对" 的核心逻辑:
- 入栈过程:遇到左括号就入栈,保证 "后入栈的左括号先参与匹配"。
- 出栈校验:遇到右括号就检查栈顶左括号是否匹配,匹配则出栈,不匹配则直接判定错误。
- 通过栈的栈顶指针
top(也就是数组的下标)管理元素的入栈、出栈操作。
【讲解步骤】
- 整体解题分为 3 个核心步骤:
- 我们采用数组模拟栈的方式实现括号匹配
- 数组
stack对应栈的存储空间,每个元素存储左括号[或( - 变量
top作为 "栈顶指针",存储当前栈顶的下标
- 数组
- ** 初始 "栈结构" 构建(左括号入栈 )**
- 每次遇到左括号,先执行
++top(栈顶指针上移),再将左括号存入stack[top]。 - 例如输入
[(]),遍历到'['时,top从 0 变为 1,stack[1] = '[';遍历到'('时,top变为 2,stack[2] = '('。
- 每次遇到左括号,先执行
- 匹配操作(右括号出栈校验)
- 遇到右括号
)或]时,需校验栈顶左括号是否与之匹配(这是 "出栈 + 校验" 的核心操作): - 若遇到
')',则检查栈顶元素stack[top]是否为'(':- 若匹配,执行
--top(栈顶指针下移,模拟出栈); - 若不匹配,直接判定括号不合法,输出
Wrong。
- 若匹配,执行
- 若遇到
']',则检查栈顶元素stack[top]是否为'[':- 若匹配,执行
--top; - 若不匹配,直接判定括号不合法,输出
Wrong
- 若匹配,执行
- 遇到右括号
- 结果判定
遍历结束后,通过top的值判断括号是否完全匹配:- 若
top == 0,说明所有左括号都有对应的右括号匹配,输出OK; - 若
top != 0,说明存在未匹配的左括号,输出Wrong。
- 若
- 我们采用数组模拟栈的方式实现括号匹配
参考代码
cpp
#include <iostream>
using namespace std;
int n, top; // n:没用上的变量;top:栈顶指针(指向栈最上面的元素)
string s; // 存储输入的括号字符串
char stack[260]; // 栈数组,用来存放左括号 [ (
int main(){
cin >> s; // 输入括号字符串,例如:"([])" "[(])"
int len = s.size(); // 获取字符串长度
// 遍历字符串的每一个字符
for(int i = 0; i < len; i++){
// ======================
// 情况1:遇到左括号 [ ( → 入栈
// ======================
if(s[i] == '[' || s[i] == '('){
stack[++top] = s[i]; // top先+1,再把左括号存入栈
}
// ======================
// 情况2:遇到右括号 ) → 匹配
// ======================
if(s[i] == ')'){
// 检查栈顶是不是对应的左括号 (
if(stack[top] == '('){
--top; // 匹配成功,栈顶出栈(指针减1)
}else{
cout << "Wrong"; // 不匹配,直接输出错误
return 0; // 结束程序
}
}
// ======================
// 情况3:遇到右括号 ] → 匹配
// ======================
if(s[i] == ']'){
// 检查栈顶是不是对应的左括号 [
if(stack[top] == '['){
--top; // 匹配成功,栈顶出栈
}else{
cout << "Wrong"; // 不匹配,输出错误
return 0;
}
}
}
// ======================
// 遍历完所有字符后
// 如果栈空(top=0)→ 所有括号都匹配成功
// 如果栈不空 → 有多余左括号,匹配失败
// ======================
if(top == 0){
cout << "OK"; // 完全匹配
}else{
cout << "Wrong"; // 有剩余左括号
}
return 0;
}
二、 铁轨问题
时间限制:1秒 内存限制:128M
题目描述
每辆火车都从A方向驶入车站C,再从B方向驶出车站C,同时它的车厢可以进行某种形式的重新组合。组合方式为:最晚驶入车站C的车厢停在最前边,可以在任意时间将停在最前边的车厢驶出车站C。假设从A方向驶来的火车有n节车厢(n<1000),分别按顺序编号为1,2,...n。假设在进入车站之前每节车厢之间都是不连着的,并且他们可以自由移动,直接倒出在B方向的铁轨上。另外假设车站C里可以停放任意多节车厢。但是一旦当一节车厢进入车站C,它就不能再回到A方向的铁轨上,并且一旦当它进入B方向的铁轨后,它就不能再回到车站C。负责车厢调度的工作人员需要知道能否使用它以a1, a2, ...an的顺序从B方向输出,请写一个程序,用来判断能否得到指定的车厢顺序。
输入描述
第一行,一个整数n,表示有n节车厢;接下来一行有n个整数,表示对应顺序
输出描述
输出仅1行。若可以,则输出"Possible"否则输出"Impossible"
样例
输入
bash
5
3 5 4 2 1
输出
bash
Possible
解题思路:
【题目剖析】
- A 方向铁轨 :
- 对应 "按 1~n 顺序排列的待入栈车厢",用变量
c标记 "下一个要进入车站 C 的车厢编号"(初始c=1,即先调度 1 号车厢)。
- 对应 "按 1~n 顺序排列的待入栈车厢",用变量
- 车站 C :
- 用静态数组
stack模拟(栈的核心特性:最晚进入的车厢在最前,符合题目 "后进先出" 的调度规则),top为栈顶指针(top=0表示栈空,即车站 C 无车厢)。
- 用静态数组
- B 方向铁轨 :
- 对应 "目标输出顺序",用数组
a存储(a[i]表示第i个需要从 B 方向驶出的车厢编号)。
- 对应 "目标输出顺序",用数组
- 调度规则 :
- 车厢从 A→C 后不能回 A,从 C→B 后不能回 C,本质是 "栈的入栈不可逆、出栈不可逆"


【讲解步骤】
这个题目详细讲解 "遍历目标序列 a,通过栈的入栈 / 出栈操作,验证能否依次匹配每个目标车厢"。
- 历目标序列,逐个匹配车厢
外层循环 for(i:1~n) 遍历目标数组 a,每次要匹配 "第 i 个需要驶出到 B 的车厢 a[i]"。
- 入栈操作 ------ 补充车厢到车站 C
当 "车站 C 为空(top=0)" 或 "车站 C 最前面的车厢(栈顶元素stack[top])不是当前目标a[i]" 时,需要从 A 方向调度下一节车厢进入 C,即执行入栈:
- 用
stack[++top] = c++实现入栈:先将top上移(栈顶位置更新),再把当前待入栈的车厢c存入栈,最后c自增(指向下一节待调度的车厢)。 - 关键判断
if(c > n):若c超过总车厢数n,说明 A 方向所有车厢已进入 C,但栈顶仍不匹配目标 ------ 此时无法继续调度,直接输出Impossible并终止程序。
- 出栈操作 ------ 匹配成功,驶出到 B
当栈顶stack[top]等于目标a[i]时,说明车站 C 最前面的车厢正是需要驶出到 B 的车厢,执行出栈:- 用
--top实现出栈:将top下移(栈顶位置更新,相当于移除栈顶元素,模拟车厢从 C 驶入 B)。
- 用
- 结果判定:所有目标匹配即成功
当外层循环遍历完所有目标(i 从 1 到 n),说明每一个需要从 B 驶出的车厢都通过栈的调度成功匹配 ------ 此时输出 Possible,表示能得到指定顺序。
cpp
#include <iostream>
using namespace std;
int n, top; // n:车厢数量;top:栈顶指针
int a[1005]; // 存储目标出站序列(我们要判断是否合法)
int stack[1005]; // 模拟栈,代表火车轨道/站台
int main() {
cin >> n; // 输入车厢总数
// 输入目标出站顺序(比如 3 1 2 这样的序列)
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
int c = 1; // c 表示当前要入栈的车厢编号,从 1 开始
// 依次判断目标序列的每一个数是否合法
for (int i = 1; i <= n; i++) {
// 当栈空 或者 栈顶不是当前需要的数字时
// 就一直把新车厢压入栈中
while (top == 0 || stack[top] != a[i]) {
// 如果已经没有车厢可以入栈了,说明序列不合法
if (c > n) {
cout << "Impossible";
return 0;
}
// 车厢 c 入栈,然后 c 自增,准备下一个车厢
stack[++top] = c++;
}
// 走到这里说明:栈顶 == 目标数字 a[i]
// 直接出栈,匹配成功
--top;
}
// 所有目标都顺利匹配完成,说明出站序列合法
cout << "Possible" << endl;
return 0;
}