题目:一个平面迷宫中有一个人,迷宫中有些点起火了,火和人每个单位时间只能向相邻的格子移动,
其中有一些空间被墙壁占据,问这个人在不背或烧到的情况下,离开迷宫的最快时间。
分析:搜索。迷宫中的最短路,首先就会想到bfs;并且bfs利用队列会使状态空间按时间顺序分层。
而火的扩散过程正好符合这个时间的层次。所以我们会想到,利用两个队列,一个储存人的状态,
一个储存火的状态。按照时间顺序,先更新火蔓延的节点,再扩展人能到达的节点。
通过分析,我们发现这两个队列可以合并,只须初始化的时候,按照火节点然后是人的顺序入队即可。
(节点中加入一个是否是火节点的判断,就可以两种节点按不同的细节处理)
注意:时间是指走出迷宫的时间,到达边界后要加1;初始节点的判断。
代码:
#include<bits/stdc++.h>
using namespace std;
const int MAX = 1010;
int m, n;
char mp[MAX][MAX];
int fire[MAX][MAX]; //火
int people[MAX][MAX]; //人
int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
queue<pair<int, int> > Q;
void BFS_fire()
{
memset(fire, -1, sizeof(fire));
while ( !Q.empty() )
{
Q.pop();
}
for (int i=0; i<n; i++)
{
for (int j=0; j<m; j++)
{
if (mp[i][j] == 'F')
{
fire[i][j] = 0;
Q.push(make_pair(i, j));
}
}
}
while ( !Q.empty() ) //BFS火能烧到的地方,并且记录时间
{
pair<int, int> a;
a = Q.front();
Q.pop();
int x = a.first;
int y = a.second;
for (int i=0; i<4; i++)
{
int xx = x + dir[i][0];
int yy = y + dir[i][1];
if (xx<0 || xx>=n || yy<0 || yy>=m) continue;
if (fire[xx][yy] != -1) continue; //被烧过
if (mp[xx][yy] == '#') continue; //有墙
fire[xx][yy] = fire[x][y] + 1; //记录时间
Q.push(make_pair(xx, yy));
}
}
}
int BFS_people()
{
memset(people, -1, sizeof(people));
while ( !Q.empty() )
{
Q.pop();
}
for (int i=0; i<n; i++)
{
for (int j=0; j<m; j++)
{
if (mp[i][j] == 'J')
{
Q.push(make_pair(i, j));
people[i][j] = 0;
}
}
}
while ( !Q.empty() )
{
pair<int, int> a;
a = Q.front();
Q.pop();
int x = a.first;
int y = a.second;
if (x==0 || y==0 || x==n-1 || y==m-1)
{
return people[x][y]+1;
}
for (int i=0; i<4; i++)
{
int xx = x + dir[i][0];
int yy = y + dir[i][1];
if (xx<0 || xx>=n || yy<0 || yy>=m) continue;
if (people[xx][yy] != -1) continue; //已经走过
if (mp[xx][yy] == '#') continue; //有墙
if (fire[xx][yy] != -1 && people[x][y]+1 >= fire[xx][yy]) continue; //&& 之前是不能被火烧过 之后是到达的时间不能有火
people[xx][yy] = people[x][y] + 1; //更新时间
Q.push(make_pair(xx, yy));
}
}
return -1;
}
int main()
{
int t;
scanf("%d", &t);
while (t--)
{
scanf("%d %d", &n, &m);
//getchar();
for (int i=0; i<n; i++)
{
for (int j=0; j<m; j++)
{
cin >> mp[i][j];
}
}
BFS_fire();
int ans = BFS_people();
if(ans == -1)
{
printf("IMPOSSIBLE\n");
}
else
{
printf("%d\n",ans);
}
}
return 0;
}