测评会员优惠活动进行中 · 开通 VIP,有效期内测评不限次 VIP 优惠中 · 测评不限次 立即查看

A29396. 两头进一头出

填空题 困难

题目描述

两头进一头出

题目描述

某队列允许在其两端进行入队操作,但仅允许在一端进行出队操作。现给定入队的序列,请你判断一系列出队序列是否可能。例如按 1、2、3、4、5 的顺序入队,则 1、3、2、5、4 这样的出队序列是可以得到的,但 5、1、3、2、4 就是不可能得到的。

输入

输入首先在一行中给出两个正整数 N 和 K(≤ 10),分别是入队元素的个数和待查验的序列个数。随后一行给出 N 个两两不同的整数组成的入队序列;再跟着 K 行,每行给出由 N 个入队整数组成的出队序列。同行整数间以空格分隔。

输出

对每个需要查验的出队序列,如果是可能的,则在一行中输出 `yes`,否则输出 `no`。

样例输入

5 4
10 2 3 4 5
10 3 2 5 4
5 10 3 2 4
2 3 10 4 5
3 5 10 4 2

样例输出

yes
no
yes
no

参考答案

#include <iostream> #include <vector> #include <deque> using namespace std; // 回溯函数:尝试插入/弹出操作,验证是否匹配出队序列 bool backtrack(deque<int>& dq, const vector<int>& in, const vector<int>& out, int i, int j, int N) { // 所有出队元素匹配完成,返回成功 if (j == N) { return true; } // 尝试弹出队头(若匹配当前出队元素) if (!dq.empty() && dq.front() == out[j]) { int val = dq.front(); dq.pop_front(); // 递归检查后续匹配 if (backtrack(dq, in, out, i, j + 1, N)) { return true; } // 回溯:恢复弹出的元素 dq.push_front(val); } // 尝试插入下一个入队元素(若还有未插入的元素) if (i < N) { // 插入队头 dq.push_front(in[i]); if (backtrack(dq, in, out, i + 1, j, N)) { return true; } // 回溯:撤销队头插入 dq.pop_front(); // 插入队尾 dq.push_back(in[i]); if (backtrack(dq, in, out, i + 1, j, N)) { return true; } // 回溯:撤销队尾插入 dq.pop_back(); } // 无可行操作,返回失败 return false; } int main() { int N, K; cin >> N >> K; // 读取入队序列 vector<int> in(N); for (int i = 0; i < N; ++i) { cin >> in[i]; } // 处理K个待查验的出队序列 while (K--) { vector<int> out(N); for (int i = 0; i < N; ++i) { cin >> out[i]; } deque<int> dq; // 模拟双端队列 bool is_valid = backtrack(dq, in, out, 0, 0, N); cout << (is_valid ? "yes" : "no") << endl; } return 0; }
上一题 下一题