解题思路:本题我们需要预处理一下每片空地起火的最短时间(即dist_fires数组的值),然后再用乔所在的位置为起始点进行bfs,如果乔到达该点之前没有起火,则拓展该点。如果到达了边界点,则返回该点距离+1,否则返回-1。
C++代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
typedef pair<int, int> PII;
char g[N][N];
PII role;
vector<PII> fire;
int dist[N][N], dist_fire[N][N];
int t, r, c;
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
void bfs_fire()
{
memset(dist_fire, 0x3f, sizeof dist_fire);
queue<PII> q;
for (auto i: fire)
{
dist_fire[i.first][i.second] = 0;
q.push(i);
}
while (q.size())
{
auto t = q.front();
q.pop();
for (int i = 0; i < 4; i ++ )
{
int a = t.first + dx[i], b = t.second + dy[i];
if (a >= 0 && a < r && b >= 0 && b < c && g[a][b] == '.' && dist_fire[a][b] == 0x3f3f3f3f)
{
dist_fire[a][b] = min(dist_fire[t.first][t.second] + 1, dist_fire[a][b]);
q.push({a, b});
}
}
}
}
int bfs()
{
if (role.first == 0 || role.first == r - 1 || role.second == 0 || role.second == c - 1) return 1;
memset(dist, 0x3f, sizeof dist);
queue<PII> q;
q.push({role.first, role.second});
dist[role.first][role.second] = 0;
while (q.size())
{
auto t = q.front();
q.pop();
for (int i = 0; i < 4; i ++ )
{
int a = t.first + dx[i], b = t.second + dy[i];
if (a >= 0 && a < r && b >= 0 && b < c && g[a][b] == '.' && dist[a][b] == 0x3f3f3f3f && dist[t.first][t.second] + 1 < dist_fire[a][b])
{
dist[a][b] = dist[t.first][t.second] + 1;
if (a == 0 || a == r - 1 || b == 0 || b == c - 1) return dist[a][b] + 1;
q.push({a, b});
}
}
}
return -1;
}
int main()
{
cin >> t;
while (t -- )
{
cin >> r >> c;
for (int i = 0; i < r; i ++ ) cin >> g[i];
while (fire.size()) fire.pop_back();
for (int i = 0; i < r; i ++ )
{
for (int j = 0; j < c; j ++ )
{
if (g[i][j] == 'F') fire.push_back({i, j});
if (g[i][j] == 'J')
{
role = {i, j};
}
}
}
bfs_fire();
int flag = bfs();
if (flag == -1) cout << "IMPOSSIBLE" << endl;
else cout << flag << endl;
}
return 0;
}
创作不易,大家可以在AcWing注册账号,参与一下AC之星计划,我的邀请码是MYRGS。对题解有任何疑问可以在评论区下面评论