题意:
在一个矩形方阵里面,一个人要从一个位置走向另一个位置,其中某些地方有火源,每过一分钟,火源就会点燃相邻的点,同时相邻的点也变成了火源。人不能通过有火的点。问一个人能够安全地走到目的地去?最短时间多少?
思路:bfs1预处理着火时间 + bfs2判断是否能出去
坑点在于没明确说F是多个,虽然刚开始有些觉察,但还是抱着侥幸心理写个双向bfs,然后就错了。
正解是不管有多少着火点F,统统加入队列Q,bfs求出地图上每个点的着火时间。然后考虑Jone,从J出发,与一般不同的是扩展的时候加了限制条件,即当前时间要 < 地图上着火的时间才能走。
记得,判断边界要写在出队时,而不是入队时。否则会漏掉初始状态的判断。
#include <cstdio>
#include <queue>
#include <vector>
#include <cstring>
#include <algorithm>
#define fi first
#define se second
#define pii pair<int,int>
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const int maxn = 1005;
int moved[4][2] = {{0,1}, {1,0}, {0,-1}, {-1,0}};
char G[maxn][maxn];
int time[maxn][maxn]; // 火经过时的时间
int vis[maxn][maxn]; // 1: J走过的; 2:F走过的
int n,m;
struct Node{
int x, y, step;
Node(int a = 0, int b = 0, int c = 0):x(a),y(b),step(c){}
};
Node Jone;
queue<Node> Q1,Q2;
void clear_queue(queue<Node> &Q){
queue<Node> empty;
swap(empty,Q);
}
// 预处理每个点的起火时间
void pre_bfs(){
Node next;
while(!Q2.empty()){
// fire
Node t = Q2.front(); Q2.pop();
for(int i = 0; i < 4; ++i){
next.x = t.x + moved[i][0];
next.y = t.y + moved[i][1];
if(next.x >= 0&&next.x < n&&next.y >= 0&&next.y < m&&G[next.x][next.y] != '#'&&vis[next.x][next.y] == 0){
vis[next.x][next.y] = 1;
next.step = t.step + 1;
time[next.x][next.y] = next.step;
Q2.push(next);
}
}
}
}
int bfs(){
Node next;
Q1.push(Jone);
vis[Jone.x][Jone.y] = 1;
while(!Q1.empty()){
// Jone
Node t = Q1.front(); Q1.pop();
if(t.x==0||t.x == n-1||t.y == m-1||t.y == 0){ //到达边界
return t.step + 1;
}
for(int i = 0; i < 4; ++i){
next.x = t.x + moved[i][0];
next.y = t.y + moved[i][1];
next.step = t.step + 1;
if(next.x >= 0&&next.x < n&&next.y >= 0&&next.y < m&&G[next.x][next.y] == '.'&&vis[next.x][next.y] == 0&&next.step < time[next.x][next.y]){
/*
判断边界不能写在这里,因为会漏判队列中的初始状态,所以假设一开始就在边界,就会导致错误。
if(next.x==0||next.x == n-1||next.y == m-1||next.y == 0){ //到达边界
printf("%d %d\n",next.x,next.y);
return next.step + 1;
}
*/
vis[next.x][next.y] = 1;
Q1.push(next);
}
}
}
return -1;
}
int main()
{
//freopen("in.txt","r",stdin);
int T; scanf("%d",&T);
while(T--){
scanf("%d %d",&n,&m);
for(int i = 0; i < n; ++i){
scanf("%s",G[i]);
}
memset(vis, 0, sizeof(vis));
clear_queue(Q1); clear_queue(Q2);
for(int i = 0; i < n; ++i)
for(int j = 0; j < m; ++j)
time[i][j] = INF;
for(int i = 0; i < n; ++i){
for(int j = 0; j < m; ++j){
if(G[i][j] == 'J'){
Jone.x = i; Jone.y = j; Jone.step = 0;
}
else if(G[i][j] == 'F'){
Q2.push(Node(i,j,0));
time[i][j] = 0;
vis[i][j] = 1;
}
}
}
pre_bfs();
memset(vis,0,sizeof(vis));
int ans = bfs();
if(ans == -1) printf("IMPOSSIBLE\n");
else printf("%d\n",ans);
}
return 0;
}