直接BFS搜索即可
需要注意的是每一轮要先搜索火然后再搜索人走的位置
#include <bits/stdc++.h>
using namespace std;
constexpr int N = 0x3f3f3f3f;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
// freopen("in.dat", "r", stdin);
int t;
cin >> t;
while (t--)
{
int n, m;
cin >> n >> m;
vector<string> maze(n);
for (int i = 0; i < n; i++)
cin >> maze[i];
// unordered_set<int> used;
auto get = [](int x, int y) {
return x * 10000 + y;
};
auto valid = [&](int x, int y) {
return x <= 0 || x > n || y <= 0 || y > m || (maze[x - 1][y - 1] != '#' && maze[x - 1][y-1]!= 'F'&&maze[x-1][y-1]!='J'); //在这里面但是没有超出去
};
auto out = [&](int x, int y) {
return x <= 0 || x > n || y <= 0 || y > m;
};
queue<pair<int, int>> que;
int ans = 0x3f3f3f3f;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
if (maze[i][j] == 'F')
que.push({get(i + 1, j + 1), -100000000}); //火表示的是负数
}
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
if (maze[i][j] == 'J')
que.push({get(i + 1, j + 1), 0});
}
}
//保证先搜了火
int x, y;
int dir[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
while (!que.empty())
{
auto e = que.front();
que.pop();
if (e.second >= 0 && out(e.first / 10000, e.first % 10000))
{
ans = e.second;
break;
}
if (out(e.first / 10000, e.first % 10000))
continue;
for (int i = 0; i < 4; i++)
{
x = e.first / 10000 + dir[i][0];
y = e.first % 10000 + dir[i][1];
if (valid(x, y)){
que.push({get(x, y), e.second + 1});
if (!out(x, y))
maze[x - 1][y - 1] = maze[e.first / 10000-1][e.first % 10000-1];
}
}
}
if (ans == N)
cout << "IMPOSSIBLE" << endl;
else
cout << ans << endl;
}
}