# UVA11624 Fire! （双重BFS）

## Fire!

Joe works in a maze. Unfortunately, portions of the maze have caught on fire, and the owner of the maze neglected to create a fire escape plan. Help Joe escape the maze.

Given Joe’s location in the maze and which squares of the maze are on fire, you must determine whether Joe can exit the maze before the fire reaches him, and how fast he can do it.

Joe and the fire each move one square per minute, vertically or horizontally (not diagonally). The fire spreads all four directions from each square that is on fire. Joe may exit the maze from any square that borders the edge of the maze. Neither Joe nor the fire may enter a square that is occupied by a wall.

### Input

The first line of input contains a single integer, the number of test cases to follow. The first line of each test case contains the two integers R and C, separated by spaces, with 1 ≤ R, C ≤ 1000. The following R lines of the test case each contain one row of the maze. Each of these lines contains exactly C characters, and each of these characters is one of:

• #, a wall

• ., a passable square

• J, Joe’s initial position in the maze, which is a passable square

• F, a square that is on fire

There will be exactly one J in each test case.

### Output

For each test case, output a single line containing ‘IMPOSSIBLE’ if Joe cannot exit the maze before the fire reaches him, or an integer giving the earliest time Joe can safely exit the maze, in minutes.

### Sample Input

2
4 4
####
#JF#
#..#
#..#
3 3
###
#J.
#.F

### Sample Output

3
IMPOSSIBLE

### 链接

https://vjudge.net/problem/UVA-11624

### 代码

StatusAccepted
Time130ms
Length2464
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
const int maxn = 1010;
const int inf = 0x3f3f3f3f;
char G[maxn][maxn];
bool vis[maxn][maxn];
int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
int Time[maxn][maxn];
int n, m;

struct Node
{
int x, y, t;
Node(){}
Node(int _x, int _y, int _t) {x = _x, y = _y, t = _t;}
};

queue <Node> Fire;
queue <Node> Joe;

void init() // 初始化
{
while (!Fire.empty())
Fire.pop();
while (!Joe.empty())
Joe.pop();
memset(vis, 0, sizeof(vis));
memset(Time, 0x3f, sizeof(Time));
}

void bfs_fire() // bfs得到每个点起火的最短时间
{
while (!Fire.empty())
{
Node u = Fire.front();
Fire.pop();
for (int i = 0; i < 4; ++i)
{
int xx = u.x + dir[i][0], yy = u.y + dir[i][1], tt = u.t + 1;
if (xx >= 1 && xx <= n && yy >= 1 && yy <= m && (G[xx][yy] == '.' || G[xx][yy] == 'J') && tt < Time[xx][yy])
{
Time[xx][yy] = tt;
Fire.push(Node(xx, yy, tt));
}
}
}
}

int escape() // bfs寻找出口，但是需要判断该点是否已经起火
{
while (!Joe.empty())
{
Node u = Joe.front();
Joe.pop();
if (u.x == 1 || u.x == n || u.y == 1 || u.y == m)
return u.t + 1;
for (int i = 0; i < 4; ++i)
{
Node v(u.x + dir[i][0], u.y + dir[i][1], u.t + 1);
int xx = v.x, yy = v.y, tt = v.t;
if (xx >= 1 && xx <= n && yy >= 1 && yy <= m && !vis[xx][yy] && G[xx][yy] == '.' && tt < Time[xx][yy])
{
vis[xx][yy] = true;
Joe.push(v);
}
}
}
return 0;
}

int main()
{
int T;
scanf("%d", &T);
while (T--)
{
scanf("%d%d", &n, &m);
init();
for (int i = 1; i <= n; ++i)
{
scanf("%s", G[i]+1); // 注意，从1开始的话是G[i]+1
for (int j = 1; j <= m; ++j)
{
if (G[i][j] == 'F') // 多个着火点入队，不需要vis标记，因为我们是用着火的最短时间来判断
Fire.push(Node(i, j, 0));
else if (G[i][j] == 'J')
{
Joe.push(Node(i, j, 0)); // 初始位置
vis[i][j] = true;
}
}
}
bfs_fire(); // 预处理着火时间
int ans = escape();
if (ans > 0) // 得到走出迷宫最短时间
printf("%d\n", ans);
else
printf("IMPOSSIBLE\n");
}
return 0;
}

#include <iostream>
#include <algorithm>
#include <queue>
#include <cstring>
using namespace std;
const int maxn = 110;
const int inf = 0x3f3f3f3f;
int n, m, k;
int map[maxn][maxn];
int fire[maxn][maxn];
int dirf[8][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}, {-1, -1}, {-1, 1}, {1, -1}, {1, 1}};
int dirm[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};

void init()
{
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
fire[i][j] = map[i][j] = inf;
}

struct node
{
int x, y;
};
queue <node> q;

int main()
{
while(cin >> n >> m >> k)
{
if (n == 0 && m == 0 && k == 0)
break;
init();
char ch;
node s, t, u, v;
for (int i = 1; i <= n; ++i)
{
for (int j = 1; j <= m; ++j)
{
cin >> ch;
if (ch == 'f')
{
fire[i][j] = 0;
u.x = i, u.y = j;
q.push(u);
}
else if (ch == 's')
{
map[i][j] = 0;
s.x = i, s.y = j;
}
else if (ch == 't')
t.x = i, t.y = j;
}
}
while (!q.empty()) // 预处理
{
u = q.front();
q.pop();
for (int i = 0; i < 8; ++i)
{
v.x = u.x + dirf[i][0];
v.y = u.y + dirf[i][1];
if (fire[v.x][v.y] > fire[u.x][u.y] + k)
{
fire[v.x][v.y] = fire[u.x][u.y] + k;
q.push(v);
}
}
}
q.push(s);
while (!q.empty()) // 迷宫问题
{
u = q.front();
q.pop();
for (int i = 0; i < 4; ++i)
{
v.x = u.x + dirf[i][0];
v.y = u.y + dirf[i][1];
if (v.x <= n && v.x >= 1 && v.y >= 1 && v.y <= m)
{
if (map[u.x][u.y] + 1 >= fire[v.x][v.y]) // 着火区域
continue;
if (map[v.x][v.y] > map[u.x][u.y] + 1)
{
map[v.x][v.y] = map[u.x][u.y] + 1;
q.push(v);
}
}
}
}
if (map[t.x][t.y] == inf)
cout << "Impossible" << endl;
else
cout << map[t.x][t.y] << endl;
}
return 0;
}

The end.
2018-07-24 星期二