献给阿尔吉侬的花束

GitHub跳转原题关系图返回列表

把迷宫看作无权图,从 S 出发做一次 BFS,首次到达 E 的步数即为最短时间;若 E 不可达则输出 oop!。

OJ: roj

题目 ID: 1256

难度:入门

标签:BFS网格最短路

创建: 2026-09-30 02:01

更新: 2026-10-05 07:12

题目描述

阿尔吉侬要从 S 走到 E,R×CR\times C 网格上 . 可走、# 为墙,每步上下左右走一格,求最少步数,不可达输出 oop!。1≤T≤101\le T\le 10,2≤R,C≤2002\le R,C\le 200,每组恰有一个 S 和 E。样例(输入→输出):

text
3 / 3 4 / .S.. / ###. / ..E. / 3 4 / .S.. / .E.. / .... / 3 4 / .S.. / #### / ..E. → 5 / 1 / oop!

思路

把每个可达格子看成一个点,相邻可达格点连边权 1,从 S 做 BFS,首次到达 E 的层数即为最少步数;队列空仍未到 E 则输出 oop!。

参考代码

Python 版:

python
#!/usr/bin/env python3
# Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
# rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
# rainboy的学习导航网站: https://idx.roj.ac.cn
# create_at: 2026-07-05 21:47
# update_at: 2026-07-05 21:47

import sys
from collections import deque


def solve() -> None:
    data = sys.stdin.buffer.read().split()
    it = iter(data)
    T = int(next(it))
    out: list[str] = []

    for _ in range(T):
        R = int(next(it))
        C = int(next(it))
        grid = [list(next(it).decode()) for _ in range(R)]

        # 定位起点 S 与终点 E
        for r in range(R):
            for c in range(C):
                if grid[r][c] == 'S':
                    sr, sc = r, c
                elif grid[r][c] == 'E':
                    tr, tc = r, c

        dist = [[-1] * C for _ in range(R)]
        dist[sr][sc] = 0
        q = deque([(sr, sc)])

        while q:
            r, c = q.popleft()
            if (r, c) == (tr, tc):
                break
            d = dist[r][c] + 1
            for nr, nc in ((r - 1, c), (r + 1, c), (r, c - 1), (r, c + 1)):
                if 0 <= nr < R and 0 <= nc < C and grid[nr][nc] != '#' and dist[nr][nc] == -1:
                    dist[nr][nc] = d
                    q.append((nr, nc))

        out.append(str(dist[tr][tc]) if dist[tr][tc] != -1 else 'oop!')

    print('\n'.join(out))


if __name__ == "__main__":
    solve()

C++ 版(同一算法):

cpp
/**
 * Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
 * rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
 * rainboy的学习导航网站: https://idx.roj.ac.cn
 * create_at: 2026-10-05 07:12
 * update_at: 2026-10-05 07:12
 */

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <utility>
using namespace std;

typedef long long ll;

const int MAXN = 205;

int R, C;
char g[MAXN][MAXN]; // 地图,'S' 起点、'E' 终点、'.' 可通行、'#' 障碍
int dist_[MAXN][MAXN]; // 到达 (r,c) 的最短步数,-1 表示未访问

int dr[4] = {-1, 1, 0, 0};
int dc[4] = {0, 0, -1, 1};

// BFS 找 S 到 E 的最少步数;不可达返回 -1
int bfs(int sr, int sc, int tr, int tc) {
    for (int r = 0; r < R; ++r)
        for (int c = 0; c < C; ++c)
            dist_[r][c] = -1;

    queue<pair<int,int> > q;
    dist_[sr][sc] = 0;
    q.push(make_pair(sr, sc));

    while (!q.empty()) {
        pair<int,int> cur = q.front();
        q.pop();
        int r = cur.first;
        int c = cur.second;
        if (r == tr && c == tc) return dist_[r][c];
        for (int k = 0; k < 4; ++k) {
            int nr = r + dr[k];
            int nc = c + dc[k];
            if (nr < 0 || nr >= R || nc < 0 || nc >= C) continue;
            if (g[nr][nc] == '#') continue;
            if (dist_[nr][nc] != -1) continue;
            dist_[nr][nc] = dist_[r][c] + 1;
            q.push(make_pair(nr, nc));
        }
    }
    return -1;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int T;
    if (!(cin >> T)) return 0;
    for (int t = 0; t < T; ++t) {
        cin >> R >> C;
        for (int r = 0; r < R; ++r) {
            for (int c = 0; c < C; ++c) {
                cin >> g[r][c];
            }
        }

        int sr = 0, sc = 0, tr = 0, tc = 0;
        for (int r = 0; r < R; ++r) {
            for (int c = 0; c < C; ++c) {
                if (g[r][c] == 'S') { sr = r; sc = c; }
                else if (g[r][c] == 'E') { tr = r; tc = c; }
            }
        }

        int ans = bfs(sr, sc, tr, tc);
        if (ans == -1) cout << "oop!";
        else cout << ans;
        if (t != T - 1) cout << "\n";
    }
    return 0;
}