# 走迷宫 - 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;
}