蒟蒻 😃 自认为是好题 对于BFS的深刻理解与灵活运用
st[ ]数组的巧妙变式
将所走的某个路径 与 是否含有钥匙 通过st[ ]数组与queue结合在一起
bfs 到某个点最短距离 可用d[ ][ ]数组直接表示
也可用 ans
注:
1️⃣ 明晰bfs思路执行过程 对于某个点偏移时 偏移后的四个点,且能走到 都是 dist + 1
2️⃣ 进行一次bfs = 对全部点进行了一次遍历 (除去联通块包围的特殊情况)
#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
const int N = 510;
char g[N][N];
int n,m;
bool st[N][N][2];
struct node
{
int aa,bb,cc,dd;
};
int dx[4] = {-1,0,1,0},dy[4] = {0,1,0,-1};
int bfs(PII start)
{
queue<node> q;
int sx = start.first,sy = start.second;
st[sx][sy][0] = true;
q.push({sx,sy,0,0});
while(q.size())
{
auto t = q.front();
q.pop();
int a = t.aa,b = t.bb,key = t.cc,dist = t.dd;
if(g[a][b] == 'E' && key) return dist;
for(int i = 0;i < 4;i++)
{
int x = a + dx[i],y = b + dy[i];
int w = key;
if(g[x][y] == 'K') w = 1; // 一旦有一个 过该点以后的所有路线
// 不管有没有或者有多个 始终w都会是1
if(x < 0 || x >= n || y < 0 || y >= m) continue;
if(g[x][y] == '#' || st[x][y][w]) continue;
if(g[x][y] == 'E' && !w) continue; // 走到出口,但没有钥匙 退出
st[x][y][w] = true;
q.push({x,y,w,dist + 1}); // 对于每一个都是 相同的dist + 1
} // 不能错误使用全局dist 即每次dist++ 最后返回 (曾经常犯的错误,还是没有清晰bfs执行过程)
}
return -1;
}
int main()
{
int T;
cin >> T;
while(T--)
{
memset(st,0,sizeof st);
scanf("%d %d",&n,&m);
for(int i = 0;i < n;i++) scanf("%s",g[i]);
PII start;
for(int i = 0;i < n;i++)
for(int j = 0;j < m;j++)
if(g[i][j] == 'P') start = {i,j};
int ans = bfs(start);
if(ans == -1) puts("No solution");
else cout << ans << endl;
}
return 0;
}