1 条题解

  • 0
    @ 2026-10-31 17:57:34

    思路

    题意简述:给定 n×mn\times m 的网格,0 不可通行,1 可通行,2 是起点,3 是终点。每步可以上下左右走一格,求从起点到终点的最少步数,无法到达输出 -1。

    这是边权全为 1 的网格最短路,用 BFS 即可:

    1. 读入时给网格外面补一圈 0,这样越界自然被视为墙,不需要额外判断边界;同时记录起点和终点坐标。
    2. 距离数组 dis 全部初始化为一个大数,起点的距离设为 0,并把起点入队。
    3. 每次取出队首 (x,y)(x,y):
      • 若它就是终点,当前距离就是最短路,直接输出并结束;
      • 否则向四个方向扩展。若新格子不是 0,且用当前距离加 1 能更新它,就更新距离并入队。
    4. 队列为空仍未到终点,说明不可达,输出 -1。

    正确性:在边权都为 1 的图上,BFS 按距离从小到大的顺序扩展结点,因此每个格子第一次被赋予的距离就是最短距离;后续不会再用更短的路径更新它。终点第一次被弹出时,其距离必然是最小步数。若队列耗尽仍没弹出终点,则不存在任何路径。

    复杂度:每个格子最多入队一次、检查四个方向,时间 O(nm)O(nm);maze、dis 两个二维数组空间也是 O(nm)O(nm)。

    代码

    #include<bits/stdc++.h>
    #define int long long
    #define dd double
    #define str string
    #define el cout << '\n'
    #define re return
    #define ff first
    #define ss second
    #define pll pair<int,int>
    #define pdd pair<dd,dd>
    #define all(x) x.begin(),x.end()
    #define pb push_back
    using namespace std;
    
    int n,m, sx,sy, ex,ey;
    // 四个移动方向:下、上、右、左
    int dx[4] = {1,-1,0,0}, dy[4] = {0,0,1,-1};
    
    void go(){
        cin>>n>>m;
        // 多开一圈边界并初始化为 0,相当于在地图外放满墙
        vector<vector<int>>maze(n+2, vector<int>(m+2, 0)), dis(n+2, vector<int>(m+2, 1e9));
    
        // 读入地图,记录起点 2 和终点 3 的位置
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                cin>>maze[i][j];
                if(maze[i][j] == 2){
                    sx=i,sy=j;
                }else if(maze[i][j] == 3){
                    ex=i, ey=j;
                }
            }
        }
    
        // 起点距离为 0,入队开始 BFS
        queue<pll>q;
        dis[sx][sy] = 0;
        q.push({sx, sy});
    
        while (q.size())
        {
            auto [x, y] = q.front();
            q.pop();
    
            // 第一次弹出终点时,距离就是最少步数
            if(x==ex and y==ey){
                cout<<dis[x][y];el;re;
            }
    
            // 向四个方向尝试松弛
            for(int i=0;i<4;i++){
                int nx = x+dx[i], ny = y+dy[i];
                // 非 0 才可通行;能走更短距离才更新并入队
                if(maze[nx][ny] != 0 and dis[nx][ny] > dis[x][y]+1){
                    dis[nx][ny] = dis[x][y]+1;
                    q.push({nx, ny});
                }
            }
        }
    
        // BFS 结束仍未到达终点,说明不可达
        cout<<-1;;el;
    }
    
    signed main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);cout.tie(nullptr);
        int _=1;
        // 本题只有一组数据,故下面的循环只执行一次
        while(_--){
            go();
        }
        return 0;
    }
    
    • 1

    信息

    ID
    54
    时间
    2000ms
    内存
    256MiB
    难度
    4
    标签
    递交数
    0
    已通过
    0
    上传者