# 走迷宫 - BFS
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
typedef pair<int, int> PII;
const int N = 110;
int n, m;
int g[N][N];
int d[N][N];
PII q[N * N];
int bfs(){
int hh = 0, tt = 0;
q[0] = {0, 0};
memset(d, -1, sizeof d);
d[0][0] = 0;
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
while(hh <= tt){
//while 队列不空
auto t = q[hh++];
//每一次取出来队头元素 即 t = 队头
for(int i = 0; i < 4; i++){
int x = t.first + dx[i], y = t.second + dy[i];
//沿着这个方向走
if(x >= 0 && x < n && y >= 0 && y < m && g[x][y] == 0 && d[x][y] == -1){
//并且在边界内的话 并且是空地可以走 并且没有走过的话
//如果不是第一次搜到即走过一次了的话就不是BFS 也就不是最短距离
//注意这里是一圈一圈搜的
d[x][y] = d[t.first][t.second] + 1;
q[++ tt] = {x, y};
//将这个点加入队列
}
}
}
return d[n - 1][m - 1];
//输出右下角这个点的距离
}
int main(){
cin >> n >> m;
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++)
cin >> g[i][j];
cout << bfs() << endl;
return 0;
}
![[Pasted image 20221227150900.png]]
![[Pasted image 20221227151607.png]]
![[Pasted image 20221227151454.png]]
# 只有当所有边的权重(即边权)都是 1 的时候才可以用 BFS 求最短路一般情况下都要用专门的最短路算法求最短路
//dp问题可以被看成是一种特殊的最短路问题 即最短路问题是包含dp问题的 即dp问题就是没有环的最短路
//深搜可以保证可以搜到终点 但是不能保证搜到的路径是最短的
//不是所有的最短路问题都可以用bfs来做 只有当所有边的权重都一样的时候 比如说边权=1时 可以用bfs
//一般情况下都要用专门的最短路算法求最短路
//dp问题肯定不会用最短路算法来求 因为最短路算法的时间复杂度比较高 dp问题的时间复杂度比较低
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 110;
typedef pair<int, int> PII;
int n, m;
int g[N][N];
int d[N][N];
//如果需要记录路径 只需要记录一下哪儿个点是从哪儿个点拓展出来的就可以了
PII q[N * N], Prev[N][N];
int bfs(){
int hh = 0, tt = 0;
q[0] = {0, 0};
memset(d, -1, sizeof d);//将所有距离初始化成-1 表示没有走过
d[0][0] = 0;//d第0初始化成0 表示已经走过了
//可以用向量表示往上下左右走
//上 (-1, 0) 右 (0, 1) 下 (1, 0) 左 (0, -1)
//即 -1 0 1 0
// 0 1 0 -1
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
while(hh <= tt){
auto t = q[hh++];//每次取出队头
for(int i = 0; i < 4; i++){
int x = t.first + dx[i], y = t.second + dy[i];
if(x >= 0 && x < n && y >= 0 && y < m && g[x][y] == 0 && d[x][y] == -1){
//这个判断的意思是 如果沿着这个边界走的话是在边界以内的 并且这个点是可以走的 即 != 0 并且这个点没有走过 即 d[x][y] == -1
d[x][y] = d[t.first][t.second] + 1;//BFS只有第一次搜到的才是最短距离 如果不是第一次搜到那就不是最短距离
Prev[x][y] = t;
q[++ tt] = {x, y};
//新的 x 新的 y 塞进队列
}
}
}
//输出路径
int x = n - 1, y = m - 1;
while(x || y){
// cout << x << ' ' << y << endl;
auto t = Prev[x][y];
x = t.first, y = t.second;
}
return d[n - 1][m - 1];
}
int main(){
cin >> n >> m;
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++)
cin >> g[i][j];
cout << bfs() << endl;
return 0;
}