P1135 奇怪的电梯 广搜

题目分析

这道题是一道典型的 BFS(广度优先搜索) 题目,要求计算从楼层 A 到楼层 B 的最少按键次数。电梯的移动规则是:

  • 每次可以 向上或向下 移动 K_i 层(K_i 是当前楼层 i 的数字)。

  • 如果移动后的楼层超出 1~N 的范围,则该方向不可行。

由于每次移动的代价相同(每次按键算一步),BFS 可以保证首次到达目标楼层时的按键次数最少。

代码解析(带详细注释)

#include<bits/stdc++.h>
using namespace std;

const int N = 1e5 + 10;  // 定义足够大的数组范围(题目中 N ≤ 200)

struct node {
    int x, step;  // x: 当前楼层,step: 走到当前楼层的按键次数
};

int vis[N];       // 标记数组,记录某个楼层是否被访问过
int n, a, b;      // n: 总楼层数,a: 起点,b: 终点
int k[N];         // 存储每层楼的 K_i 值
int nex[2] = {-1, 1};  // 移动方向:-1(向下),1(向上)

void bfs(int a) {
    queue<node> q;  // 定义队列,用于BFS
    vis[a] = 1;     // 标记起点已访问
    q.push({a, 0}); // 起点入队,初始按键次数为0

    while (q.size()) {  // 队列不为空时循环
        int x = q.front().x, d = q.front().step;  // 取出队首元素
        q.pop();  // 弹出队首

        // 遍历两种可能的移动方向(上、下)
        for (int i = 0; i < 2; i++) {
            int tx = x + nex[i] * k[x];  // 计算移动后的新楼层
            if (tx < 1 || tx > n) continue;  // 越界则跳过
            if (vis[tx]) continue;       // 已访问则跳过

            vis[tx] = 1;            // 标记新楼层已访问
            q.push({tx, d + 1});    // 入队,按键次数+1
            if (tx == b) {          // 如果到达终点
                cout << d + 1 << endl;  // 输出按键次数
                return;             // 直接返回
            }
        }
    }
    cout << -1 << endl;  // 队列空仍未到达终点,输出-1
}

int main() {
    cin >> n >> a >> b;  // 输入总楼层数、起点、终点
    for (int i = 1; i <= n; i++) cin >> k[i];  // 输入每层楼的 K_i

    if (a == b) {  // 特判:起点等于终点时直接输出0
        cout << 0 << endl;
        return 0;
     }
     bfs(a);
     return 0;       
}

 

posted @ 2025-06-04 20:13  CRt0729  阅读(74)  评论(0)    收藏  举报