UVa 11624 - Fire!(着火了!)
Time limit: 1.000 seconds
Description - 题目描述
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.
Joe在一个迷宫里工作。部分迷宫不幸起火,然而迷宫主人并没有制定逃生计划。帮帮Joe逃出生天吧。
给定Joe与迷宫起火部分的位置,你需要确定Joe能否在被火上身前逃出迷宫,以及最快出逃时间。
Joe与火焰每分钟都能垂直或水平(不能斜向)移动一个格子。每个着火的格子都会向全部四个方向传播火焰。Joe可以从任意迷宫边缘的格子逃出去。Joe和火焰都无法穿墙。
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.
输入的第一行为一个整数,表示测试用例的数量。 每组测试用例的第一行有两个整数R和C,以空格隔开,且1 ≤ R; C ≤ 1000。 随后R行,每行表示其中迷宫中的其中一行。每行C个字符,各字符如下: • #, 墙 • ., 可通行的格子 • J, Joe的初始位置, 在一块可通行格子上 • F, 火焰所在的格子 每组测试用例只有一个J。
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.
对于每组测试用例,如果Joe无法火焰烧到他前逃出则输出‘IMPOSSIBLE’,否则输出一个整数表示Joe逃出迷宫的最早时间,单位分钟。
Sample Input - 输入样例
2 4 4 #### #JF# #..# #..# 3 3 ### #J. #.F
Sample Output - 输出样例
3 IMPOSSIBLE
题解
一般BFS
可以把火和人分别拆成2个BFS。
或二者合并,先搜索火焰传播,在搜索人是否可以移动。
代码 C++
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <queue> 5 #define INF 0x7F7F7F7F 6 #define MX 1005 7 struct Point { 8 int y, x; 9 }J, now, nxt; 10 std::queue<Point> q; 11 int data[MX][MX], fx[8] = { 1, 0, -1, 0, 0, 1, 0, -1 }, y, x, opt; 12 char map[MX][MX]; 13 void BFS() { 14 int i, tmp; 15 q.push(J); 16 while (!q.empty()) { 17 now = q.front(); q.pop(); tmp = data[now.y][now.x] + 1; 18 if (now.y == 1 || now.y == y || now.x == 1 || now.x == x) { 19 if (map[now.y][now.x] == 'J') { opt = std::min(opt, tmp); continue; } 20 } 21 for (i = 0; i < 8; i += 2) { 22 nxt = { now.y + fx[i], now.x + fx[i + 1] }; 23 if (map[nxt.y][nxt.x] == '.' && tmp < data[nxt.y][nxt.x]) { 24 map[nxt.y][nxt.x] = map[now.y][now.x]; data[nxt.y][nxt.x] = tmp; 25 q.push(nxt); 26 } 27 } 28 } 29 } 30 int main() { 31 int t, i, j; 32 scanf("%d", &t); 33 while (t--) { 34 memset(map, 0, sizeof map); memset(data, INF, sizeof data); 35 opt = INF; 36 scanf("%d%d ", &y, &x); 37 for (i = 1; i <= y; ++i) gets(&map[i][1]); 38 for (i = 1; i <= y; ++i) for (j = 1; j <= x; ++j) { 39 switch (map[i][j]) { 40 case 'J': J = { i, j }; data[i][j] = 0; break; 41 case 'F': q.push({ i, j }); data[i][j] = 0; break; 42 } 43 } 44 BFS(); 45 if (opt == INF) puts("IMPOSSIBLE"); 46 else printf("%d ", opt); 47 } 48 return 0; 49 }