有 n 层楼和一架电梯。电梯位于第 i 层楼时,向上或向下移动的层数等于一个固定的数字 ki。如果到达的层数不合法,即不在 1 和 n 之间,相应的操作就无法进行。问:从第 a 楼到第 b 楼至少操作几次电梯?如果无法到达,输出 −1。
解答
本题需要计算最短路径,这正是 BFS 擅长解决的问题。实现时,需要在队列中同时维护需要处理的楼层位置和从起点 a 出发到达当前楼层的最短距离,并配合访问标记数组避免重复加入同一个元素。一个结点 i 扩展可到达结点的时候,需要向 i+ki 和 i−ki 扩展,注意不能到达非法楼层。当扩展到尚未到达的合法楼层时,需要将它加入队列,并记录到达该楼层的最短距离为到达当前所在楼层的最短距离加一。当首次到达结点 b 时,记录的最短距离就是最终答案。
代码中,直接记录距离数组,并利用距离是否为默认值(即 −1)来判断结点是否尚未访问。
参考实现
#include <iostream>#include <queue>using namespace std;const int N = 210;int n, a, b, k[N], d[N];int main() { cin >> n >> a >> b; for (int i = 1; i <= n; ++i) cin >> k[i]; for (int i = 1; i <= n; ++i) d[i] = -1; queue<int> q; d[a] = 0; q.push(a); while (!q.empty()) { int x = q.front(); q.pop(); if (x == b) { break; } int y = x + k[x]; if (y <= n && d[y] == -1) { d[y] = d[x] + 1; q.push(y); } y = x - k[x]; if (y >= 1 && d[y] == -1) { d[y] = d[x] + 1; q.push(y); } } cout << d[b] << endl; return 0;}