UVA 11624 Fire

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.

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 R R and C C C,separated by spaces, with 1 ≤ R , C ≤ 1000 1 ≤ R, C ≤ 1000 1R,C1000. The following R R R lines of the test case each contain one row of the maze. Each of these lines contains exactly C C 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.

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.

Sample Input

2
4 4
####
#JF#
#..#
#..#
3 3
###
#J.
#.F
Sample Output
3
IMPOSSIBLE

Translation

给一张地图,一个人站在标为’J’的格点,一些格点标为’F’,是起始的着火点,火势会向上下左右蔓延,人也只能向上下左右四个方向逃窜,火和人每走一格都会消耗一分钟,问人最少花费几分钟逃出地图。

Idea

一次 B F S BFS BFS得到火走到地图上各个格子的时间,第二次 B F S BFS BFS找人的最短路径,每一个时刻,人要选择火势还没到的格子。

Code

#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
const int N=1003;
//方向向量
const int dx[]={-1,1,0,0};
const int dy[]={0,0,-1,1};
char G[N][N];//存图
int r,c;
bool vis[N][N];
int step[2][N][N];
int ans;
struct node
{
	int x,y;
};
node fire,person;
void bfs_fire()//找到各个点起火的最短时间
{
	queue<node>q;
	memset(vis,0,sizeof(vis));
	int i,j;
	for(i=1;i<=r;i++)
	{
		for(j=1;j<=c;j++)
		{
			switch(G[i][j])
			{
				case 'F':
					vis[i][j]=1;
					fire.x=i;
					fire.y=j;
					q.push(fire);//将所有起火点入队
					break;
				default: break;
			}
		}
	}
	while(!q.empty())
	{
		node now,nxt;
		now=q.front();
		int i;
		//枚举四个方向
		for(i=0;i<4;i++)
		{
			nxt.x=now.x+dx[i];
			nxt.y=now.y+dy[i];
			if(nxt.x<1||nxt.x>r) continue;
			else if(nxt.y<1||nxt.y>c) continue;
			else if(G[nxt.x][nxt.y]=='#') continue;
			else if(vis[nxt.x][nxt.y]) continue;
			else
			{
				q.push(nxt);
				vis[nxt.x][nxt.y]=1;
				step[0][nxt.x][nxt.y]=step[0][now.x][now.y]+1;
			}
		}
		q.pop();
	}
}
void bfs_person()
{
	queue<node>q;
	memset(vis,0,sizeof(vis));
	vis[person.x][person.y]=1;
	q.push(person);//起始点入队
	while(!q.empty())
	{
		int i;
		node now,nxt;
		now=q.front();
		for(i=0;i<4;i++)
		{
			//枚举四个方向
			nxt.x=now.x+dx[i];
			nxt.y=now.y+dy[i];
			if(nxt.x<1||nxt.x>r) continue;
			else if(nxt.y<1||nxt.y>c) continue;
			else if(vis[nxt.x][nxt.y]) continue;
			else if (G[nxt.x][nxt.y]=='#'||G[nxt.x][nxt.y]=='F') continue;
			/*
				如果step[0][nxt.x][nxt.y]==0说明不能走到
				要在火来临前走到该格点,如果不能则continue
			*/
			if(step[0][nxt.x][nxt.y]!=0&&step[0][nxt.x][nxt.y]<=step[1][now.x][now.y]+1) continue;
			else
			{
				step[1][nxt.x][nxt.y]=step[1][now.x][now.y]+1;
				//走到边界
				if(nxt.x==1||nxt.x==r||nxt.y==c||nxt.y==1)
				{
					ans=step[1][nxt.x][nxt.y]+1;
					return;
				}
				else 
				{
					vis[nxt.x][nxt.y]=1;
					q.push(nxt);
				}
			}
		}
		q.pop();//出队
	}
}
void init()//初始化
{
	memset(step,0,sizeof(step));
	ans=-1;
}
void solve()
{
	init();
	int i,j;
	cin>>r>>c;
	for(i=1;i<=r;i++)
	{
		for(j=1;j<=c;j++)
		{
			cin>>G[i][j];
			switch(G[i][j])
			{
				case 'J':
					person.x=i;
					person.y=j;
					step[1][i][j]=0;
					break;
				default: break;
			}
		}
	}
	if(person.x==1||person.x==r||person.y==c||person.y==1) ans=1;//特判
	else//两次BFS
	{
		bfs_fire();
		bfs_person();
	}
	if(ans==-1) puts("IMPOSSIBLE");//没有被更新
	else cout<<ans<<endl;
}
int main()
{
	int t;
	cin>>t;
	while(t--) solve();
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值