![](https://i-blog.csdnimg.cn/blog_migrate/138016449c95150dc72bdeca0879f88b.png)
![](https://i-blog.csdnimg.cn/blog_migrate/53e69fd31e8bbe49a4bc5c9cfda15b3b.png)
![](https://i-blog.csdnimg.cn/blog_migrate/c447b6e154eb6a2c8b18f945ec095b45.png)
![](https://i-blog.csdnimg.cn/blog_migrate/e477e99c75c2c0eaf311d4d8ff511823.png)
![](https://i-blog.csdnimg.cn/blog_migrate/b4c03bbc08ce306d0b98200ecd1d75b6.png)
![](https://i-blog.csdnimg.cn/blog_migrate/521dcfc8d75f736b3911bc295206ee17.png)
![](https://i-blog.csdnimg.cn/blog_migrate/df6020f93be0a13357e2a10229e16bef.png)
![](https://i-blog.csdnimg.cn/blog_migrate/2e1435294ec91946c2cba1ee4ffc4120.png)
![](https://i-blog.csdnimg.cn/blog_migrate/26a61b0ec1f17bc3b94abcb567ab4bbd.png)
![](https://i-blog.csdnimg.cn/blog_migrate/d13c988d51877de5891f8fbb822c90c0.png)
这道题更适合使用广度优先搜索(BFS)而不是深度优先搜索(DFS)的主要原因是:
BFS可以找到从起点到终点的最短路径。
深度优先搜索通常会在搜索到一个路径后一直探索下去,直到无法再继续,然后返回上一层继续搜索。
虽然在某些情况下深度优先搜索可能会找到解决方案,但是由于深度优先搜索不会考虑路径的长度,
因此不能保证找到的解是最短的。
而广度优先搜索则会逐层搜索,先访问离起点最近的节点,然后是离起点距离为2的节点,依此类推。
这样一层一层地搜索下去,直到找到终点为止。
因此,当我们发现终点时,通过BFS得到的路径一定是从起点到终点的最短路径。
在本题中,我们可以将混境之地的每个位置看作图中的一个节点,相邻的可通行位置之间存在一条边。
通过BFS搜索,我们可以从起点开始逐步向外扩展搜索,
直到找到出口位置,这样就可以保证找到的路径是最短路径,从而得到小蓝逃离混境之地所需的最少时间。
#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
char mi[N][N];//迷宫矩阵
int dist1[N][N];//dist1 表示从起点到(i,j)的最短距离
int dist2[N][N];//dist2 表示从终点到(i,j)的最短距离
vector<pair<int, int>> key;//存储所有傲视的横纵坐标
int dx[4] = {1,0,-1,0};
int dy[4] = {0,-1,0,1};
bool has_key = false;//是否有钥匙
int n,m;
int start_x,start_y;//起点
int end_x,end_y;//终点
bool in_map(int x,int y)//判断合不合法
{
if(x <= 0 || y <= 0 || x > n || y > m)
{
return false;
}
if(mi[x][y] == '#')
{
return false;
}
return true;
}
void bfs(int x,int y,int dist[][N])
{
dist[x][y] = 0;//从起点到起点的距离为0
queue<pair<int , int>> q;
q.push({x,y});
while(!q.empty())
{
auto t = q.front();
q.pop();
for(int i = 0 ; i < 4; i++)
{
//取出当前坐标
int now_x = t.first;
int now_y = t.second;
//计算当前新的坐标
int new_x = now_x + dx[i];
int new_y = now_y + dy[i];
//要合法且访问,且最短距离可以更新
if(in_map(new_x,new_y) && dist[new_x][new_y] > dist[now_x][now_y]+1)
{
dist[new_x][new_y] = dist[now_x][now_y] + 1;//更新最短距离
q.push({new_x,new_y});
}
}
}
}
signed main()
{
//初始化为极大值
memset(dist1,0x3f,sizeof(dist1));
memset(dist2,0x3f,sizeof(dist2));
cin>>n>>m;
cin>>start_x>>start_y;
cin>>end_x>>end_y;
for(int i = 1 ; i <= n; i ++)
{
for(int j = 1 ; j <= m ; j ++)
{
cin>>mi[i][j];
if(mi[i][j] == 'k')
{
has_key = true;//存在钥匙
key.emplace_back(i,j);//记录坐标
}
}
}
if(!has_key)//没钥匙一定走不出去
{
cout<<-1<<endl;
return 0;
}
bfs(start_x,start_y,dist1);//从起点开始bfs,计算各点到起点的最小距离
bfs(end_x,end_y,dist2);//同理,终点
int ans = 1e9;
for(int i = 0 ; i < key.size() ; i++)
{
int x = key[i].first;
int y = key[i].second;
/*
* 要走出迷宫,需要先从起点走到钥匙,再从钥匙走到终点
* 前者走的距离为dist1,后者走的距离为dist2
* 然后用小的不断更新
*/
ans = min(ans,dist1[x][y]+dist2[x][y]);
}
if(ans < 1e9)//如果更新了
{
cout<<ans<<endl;
}
else cout<<"-1"<<endl;//没更新,说明无法走出
return 0;
}