相信大家已经读过题目了,我就搬一下洛谷的翻译:
题目大意 你的任务是帮助Joe走出一个大火蔓延的迷宫。Joe每分钟可以走到上下左右4个方向的相邻格子之一,而所有着火的格子都会四周蔓延(即如果某个空格子与着火格子有公共边,则下一分钟这个空格子将着火)。迷宫中有一些障碍格,Joe和火都无法进入。当Joe走到一个迷宫的边界格子时,我们认为他已经出了迷宫。
输入数据 第一行为数据组数T。每一组测试数据格式如下: 第一行为两个整数R和C(1<=R,C<=1000)。以下R行每行有C个字符,即迷宫,其中“#”表示墙和障碍物,“.”表示空地,“J”是joe的初始位置(也就是空地),”F”是着火格子。每组数据的迷宫中恰好有一个格是”J”。
输出数据 对于每组测试数据,如无法走出迷宫,则输出IMPOSSIBLE,否则输出走出迷宫的最短时间(单位:分钟)。
输入
2
4 4
####
#JF#
#..#
#..#
3 3
###
#J.
#.F
输出
3
IMPOSSIBLE
题解:首先要注意火是不止一个的,我们分开设置两个搜索,一个搜索火到每个位置的时间,另一个搜索杰克走的路径,如果火比杰克提前到那个位置,杰克就不可以走那个位置。
本人因没有设置火到不了的地方为极大值wa了九发。
#pragma GCC optimize(3,"Ofast","inline")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <math.h>
#include <string>
#include <list>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <algorithm>
#define maxn 1000000
//#define true false
//#define false true
const int MaxN=0x3f3f3f3f;
const int MinN=0xc0c0c00c;
const double pi=acos(-1);
typedef long long ll;
const int mod=1e9+7;
using namespace std;
int n,m;
char a[1010][1010];
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
bool visited[1010][1010];
struct wazxy{
int x,y;
int steps;
}temp,node;
int times[1010][1010]; //记录火的出现次数
queue <wazxy> fire,jack;
int ans;
void bfs_fire(){
for(int i=1;i<=n;i++) //把火挨着放进队列
for(int f=1;f<=m;f++){
if(a[i][f]=='F'){
temp.x=i,temp.y=f,temp.steps=0;
visited[i][f]=false;
times[i][f]=0;
fire.push(temp);
}
}
while(!fire.empty()){ //开始搜索,标记火什么时候出现在什么位置
node=fire.front();
times[node.x][node.y]=node.steps;
fire.pop();
for(int i=0;i<4;i++){
if(visited[node.x+dx[i]][node.y+dy[i]]&&((a[node.x+dx[i]][node.y+dy[i]]=='J')||(a[node.x+dx[i]][node.y+dy[i]]=='.'))){
visited[node.x+dx[i]][node.y+dy[i]]=false;
temp.x=node.x+dx[i],temp.y=node.y+dy[i],temp.steps=node.steps+1;
fire.push(temp);
}
}
}
return ;
}
void bfs_jack(int x,int y){
node.steps=0,node.x=x,node.y=y;
jack.push(node);
while(!jack.empty()){
temp=jack.front();
jack.pop();
if(temp.x>n||temp.x<1||temp.y>m||temp.y<1){ //我的判断依据是他超出地图即为跑出去,因为地图是从1开始所以不会re
ans=temp.steps;
return ;
}
if(times[temp.x][temp.y]<=temp.steps) continue; //这一点千万注意,如果火比jack早到了这一点,就把这一点作废
for(int i=0;i<4;i++){
if(visited[temp.x+dx[i]][temp.y+dy[i]]&&a[temp.x+dx[i]][temp.y+dy[i]]!='#'){
visited[temp.x+dx[i]][temp.y+dy[i]]=false;
node.x=temp.x+dx[i],node.y=temp.y+dy[i],node.steps=temp.steps+1;
jack.push(node);
}
}
}
return ;
}
int main()
{
int t;
//freopen("in.txt","r",stdin);
cin>>t;
while(t--){
while(!jack.empty()) jack.pop(); //不要忘记清空队列
while(!fire.empty()) fire.pop();
cin>>n>>m;
for(int i=0;i<1010;i++){
for(int f=0;f<1010;f++){ //赋初值没有到达的地方附上极大值
times[i][f]=MaxN;
}
}
int x,y;
getchar();
memset(visited,true,sizeof(visited));
memset(a,0,sizeof(a));
for(int i=1;i<=n;i++){
scanf("%s",a[i]+1);
}
// for(int i=1;i<=n;i++){
// for(int f=1;f<=m;f++)
// cout<<a[i][f]<<" ";
// cout<<endl;
// }
bfs_fire();
for(int i=1;i<=n;i++){
for(int f=1;f<=m;f++){
if(a[i][f]=='J'){
x=i,y=f;
break;
}
}
}
ans=-1;
memset(visited,true,sizeof(visited));
bfs_jack(x,y);
if(ans==-1) cout<<"IMPOSSIBLE"<<endl;
else cout<<ans<<endl;
}
return 0;
}