1 条题解
-
0
思路
题意简述:给定 的网格,
0不可通行,1可通行,2是起点,3是终点。每步可以上下左右走一格,求从起点到终点的最少步数,无法到达输出-1。这是边权全为 1 的网格最短路,用 BFS 即可:
- 读入时给网格外面补一圈
0,这样越界自然被视为墙,不需要额外判断边界;同时记录起点和终点坐标。 - 距离数组
dis全部初始化为一个大数,起点的距离设为 0,并把起点入队。 - 每次取出队首 :
- 若它就是终点,当前距离就是最短路,直接输出并结束;
- 否则向四个方向扩展。若新格子不是
0,且用当前距离加 1 能更新它,就更新距离并入队。
- 队列为空仍未到终点,说明不可达,输出
-1。
正确性:在边权都为 1 的图上,BFS 按距离从小到大的顺序扩展结点,因此每个格子第一次被赋予的距离就是最短距离;后续不会再用更短的路径更新它。终点第一次被弹出时,其距离必然是最小步数。若队列耗尽仍没弹出终点,则不存在任何路径。
复杂度:每个格子最多入队一次、检查四个方向,时间 ;
maze、dis两个二维数组空间也是 。代码
#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
- 上传者