题目描述:在一个n*m大小的网格中,1代表障碍物,0代表可以通过,从左上角走到右下角,每次只能上下左右移动一格,求最短路径长度。
示例输入:
5 5 0 0 0 0 1 0 1 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0
示例输出:
13
#include <iostream>
#include <queue>
using namespace std;
const int N = 110;
int n, m;
int g[N][N]; // 存储地图(0表示可以通过,1表示障碍物)
int dis[N][N]; // 存储每个位置到起点的最短路径长度,初始化为-1
int dx[4] = {-1, 0, 1, 0}; // 四个方向的x坐标变化
int dy[4] = {0, 1, 0, -1}; // 四个方向的y坐标变化
struct Node { // 存储每个位置的坐标
int x, y;
};
// 判断当前位置是否可以走(不越界且不是障碍物且之前没有被访问过)
bool check(int x, int y) {
if (x < 0 || x >= n || y < 0 || y >= m || g[x][y] == 1 || dis[x][y] != -1) {
return false;
}
return true;
}
void bfs() {
queue<Node> q;
q.push({0, 0});
dis[0][0] = 0; // 起点到起点的距离为0
while (!q.empty()) {
auto t = q.front();
q.pop();
for (int i = 0; i < 4; i++) {
int x = t.x + dx[i];
int y = t.y + dy[i];
if (check(x, y)) { // 如果当前位置可以走,就进队
q.push({x, y});
dis[x][y] = dis[t.x][t.y] + 1; // 更新最短路径长度
}
}
}
}
int main() {
cin >> n >> m;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cin >> g[i][j];
dis[i][j] = -1; // 初始化为-1
}
}
bfs();
cout << dis[n - 1][m - 1]; // 输出终点到起点的最短路径长度
return 0;
}
代码讲解:
- 定义
g
数组存储地图,定义dis
数组存储每个位置到起点的最短路径长度,初始化为-1。定义dx
数组和dy
数组存储四个方向的坐标变化。- 定义一个
check
判断函数,判断当前位置是否可以走。若越界、为障碍物或已访问过,则返回假,否则返回真。- 首先将起点加入队列,并将起点到起点的距离为0。
- 当队列不空时,取出队首位置
t
,并向四个方向探索。若当前位置可以走,则将当前位置加入队列,并更新最短路径长度。- 当队列为空时,结束搜索。
- 输出终点到起点的最短路径长度
dis[n-1][m-1]
。