题目链接:UVA 11624 Fire!
题目大意:
一个平面迷宫中有一个人,迷宫中有些点起火了,火和人每个单位时间只能向相邻的格子移动,其中有一些空间被墙壁占据,问这个人在不被烧到的情况下,离开迷宫的最快时间。
题解:
首先用BFS预处理大火覆盖每一个能达到的地方的时间,之后再对人用BFS,只要人在大火之前到达一个地方,即为安全。
注意初始的火不一定只有一处。
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
#define ms(a, b) memset(a, b, sizeof(a))
#define io_speed_up ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MAXN 1000 + 10
#define INF 0x3f3f3f3f
int t, n, m, step[MAXN][MAXN], sx, sy;
bool vis[MAXN][MAXN];
char a[MAXN][MAXN];
struct node {
int x, y, t;
};
queue <node> q;
const int dx[] = {0, 0, 1, -1};
const int dy[] = {1, -1, 0, 0};
void fireBfs() {
while (!q.empty()) {
node u = q.front();
q.pop();
for (int i = 0; i < 4; ++i) {
int xi = u.x + dx[i], yi = u.y + dy[i];
if ((xi >= 1 && xi <= n && yi >= 1 && yi <= m) && a[xi][yi] != '#' && step[xi][yi] == INF) {
q.push(node{xi, yi, 0});
step[xi][yi] = step[u.x][u.y] + 1;
}
}
}
}
void JoeBfs() {
q.push(node{sx, sy, 0});
vis[sx][sy] = true;
while (!q.empty()) {
node u = q.front();
q.pop();
if (u.x == n || u.x == 1 || u.y == 1 || u.y == m) {
cout << u.t + 1 << endl;
return;
}
for (int i = 0; i < 4; ++i) {
int xi = u.x + dx[i], yi = u.y + dy[i];
if ((xi >= 1 && xi <= n && yi >= 1 && yi <= m) && a[xi][yi] != '#' && !vis[xi][yi] && (u.t + 1 < step[xi][yi])) {
q.push(node{xi, yi, u.t + 1});
vis[xi][yi] = true;
}
}
}
cout << "IMPOSSIBLE" << endl;
}
int main() {
io_speed_up;
cin >> t;
while (t--) {
while (!q.empty()) q.pop();
ms(vis, false);
ms(step, INF);
cin >> n >> m;
for (int i = 1; i <= n; ++i) cin >> a[i] + 1;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
if (a[i][j] == 'J') {
sx = i;
sy = j;
}
if (a[i][j] == 'F') {
q.push(node{i, j, 0});
step[i][j] = 0;
}
}
}
fireBfs();
while (!q.empty()) q.pop();
JoeBfs();
}
return 0;
}