【题意】一个平面迷宫中有一个人,迷宫中有些点起火了,火和人每个单位时间只能向相邻的格子移动,
其中有一些空间被墙壁占据,问这个人在不背或烧到的情况下,离开迷宫的最快时间。
【分析】如果没有火,那么本题是一个标准的迷宫问题,可以用BFS解决。加上了火,难度增加了多少呢?其实没多少。注意,火是不能自动熄灭的,因此只要某个格子在某时刻起火了,以后将一直如此。所以只需要预处理每个格子起火的时间,在bfs扩展节点的时候加一个判断,当到达新节点时该格子没着火才真正的把这个新的节点加入到队列中。
最后需要考虑一下如何求出每个格子起火的时间,其实这也是一个最短路问题,只不过起点不是一个,而是多个(所有的初始着火点)。这只是需要在初始队列时把所有着火点都放进去即可。
两个步骤的时间复杂度均为O(RC).
【AC代码】
#include <set>
#include <map>
#include <queue>
#include <cstring>
#include <vector>
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1010;
int n,m;
char maze[maxn][maxn];
int a[maxn][maxn];
int b[maxn][maxn];
struct node{
int x,y;
node(){}
node(int x,int y):x(x),y(y){}
};
int dir[4][2] = {{0,1},{0,-1},{-1,0},{1,0}};
void bfs1(){
queue<node>qu;
while(!qu.empty()) qu.pop();
memset(a,-1,sizeof(a));
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
if(maze[i][j]=='F'){
a[i][j]=0;
qu.push(node(i,j));
}
}
}
while(!qu.empty()){
node tmp = qu.front();
qu.pop();
for(int i=0; i<4; i++){
int dx = tmp.x+dir[i][0];
int dy = tmp.y+dir[i][1];
//if(dx<0||dx>=n||dy<0||dy>=m||a[dx][dy]!=-1||maze[dx][dy]=='#') continue;
if(dx<0||dx>=n||dy<0||dy>=m) continue;
if(a[dx][dy]!=-1) continue;
if(maze[dx][dy]=='#') continue;
a[dx][dy] = a[tmp.x][tmp.y]+1;
qu.push(node(dx,dy));
}
}
}
int bfs2(){
queue<node>qu;
while(!qu.empty()) qu.pop();
memset(b,-1,sizeof(b));
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
if(maze[i][j]=='J'){
b[i][j] = 0;
qu.push(node(i,j));
}
}
}
while(!qu.empty()){
node tmp = qu.front();
qu.pop();
if(tmp.x==0||tmp.x==n-1||tmp.y==0||tmp.y==m-1){
return b[tmp.x][tmp.y]+1;
}
for(int i=0; i<4; i++){
int dx = tmp.x+dir[i][0];
int dy = tmp.y+dir[i][1];
if(dx<0||dx>=n||dy<0||dy>=m) continue;
if(b[dx][dy]!=-1) continue;
if(maze[dx][dy]=='#') continue;
if(a[dx][dy]!=-1&&b[tmp.x][tmp.y]+1>=a[dx][dy]) continue;
b[dx][dy] = b[tmp.x][tmp.y]+1;
qu.push(node(dx,dy));
}
}
return -1;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d %d",&n,&m);
for(int i=0; i<n; i++) scanf("%s",maze[i]);
bfs1();
int ans = bfs2();
if(ans==-1){
printf("IMPOSSIBLE\n");
}else{
printf("%d\n",ans);
}
}
return 0;
}