UVA11624-Fire!(BFS)

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

题目描述
乔在迷宫中工作。不幸的是,迷宫的一部分着火了,迷宫的主人没有制定火灾的逃跑计划。请帮助乔逃离迷宫。根据乔在迷宫中的位置以及迷宫的哪个方块着火,你必须确定火焰烧到他之前,乔是否可以离开迷宫,如果能离开他能跑多快。
乔和火每分钟移动一个方格,上、下、左、右,四个方向中的一个。火势向四个方向同时蔓延。乔可以从迷宫的任何一个边界逃离迷宫。无论是乔还是火都不会到达有墙的位置。
输入
第一行输入包含一个整数,即测试次数
每个测试用例的第一行包含两个
整数R和C,用空格分隔,1≤R,C≤1000
下面R行中,每一行都包含C个字符,以及每个字符是以下之一:
‘#’ 代表墙
. 代表空地,火和乔是可通行的
J 乔在迷宫中最初的位置,火和乔是可通行的
F 代表火
在每组测试中只有一个J
输出
对于每个测试用例,如果在火蔓延的时候烧到了乔,则乔无法逃出迷宫,输出’IMPOSSIBLE’如果乔能逃出迷宫,则输出乔最快可以在几分钟内安全逃出迷宫,每组输出占一行
样例输入
2
4 4

#JF#
#…#
#…#
3 3

#J.
#.F
样例输出
3
IMPOSSIBLE

WFU2019级训练(二)

这道题是UVA的题目,是一道BFS题,但是和以往BFS不同的是这个要搜两次,题目的意思是Joe能否在火烧到他之前找到出口并逃出迷宫,其中J代表人物,F代表火,#代表墙,. 代表空地,我们要做的就是判断火能不能在Joe逃出之前烧到Joe,思路是先搜火,需要注意的是:迷宫中可能不止一处火源!!,我们开两个数组,一个用来存放火烧的时间,一个用来存放Joe逃跑的时间,如果Joe逃跑的时间<火的时间,那这就可以走,反之则不能走,我们先处理火的数组,因为不止一处火源,所以我们先遍历整个地图,把所有火源先放入队列中,以保证所有的点扩的都是火烧的最短时间。处理完火的数组以后再处理Joe数组,把J点入队,再对这个点进行BFS,一开始令ans=-1,如果能走出去,则把步数赋值给ans,如果ans最后等于-1,则输出IMPOSSIBLE。ac代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <stack>
#include <queue>
#include <cstring>
using namespace std;
const int _max=1e3+50;
char mp[_max][_max];
int bookj[_max][_max],bookf[_max][_max];//定义两个数组
struct node {int x,y;};//用于存放坐标的节点结构体
int r,c,ans;
int main()
{
	ios::sync_with_stdio(false);
	int n;
	cin>>n;
	void bfsj();//处理Joe
	void bfsf();//处理火
	while(n--)
	{
		cin>>r>>c;
		for(int i=0;i<r;i++)
		  cin>>mp[i];
		ans=-1;
		memset(bookf,-1,sizeof(bookf));//两个数组均初始化为-1步
		memset(bookj,-1,sizeof(bookj));
		bfsf();//先处理火
		bfsj();//后处理人
		if(ans==-1)
		  cout<<"IMPOSSIBLE"<<endl;
		else
		  cout<<ans<<endl;  
	}
	return 0;
}
void bfsf()
{
	queue<node >q;
	node a;
	int next[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
	int nx,ny;
	for(int i=0;i<r;i++)
	  for(int j=0;j<c;j++)
	    if(mp[i][j]=='F')
	    {
	    	bookf[i][j]=0;
	    	a.x=i;
	    	a.y=j;
	    	q.push(a);//先将所有的火入队
		}
	while(q.empty()!=1)
	{
		for(int k=0;k<=3;k++)
		{
			nx=q.front().x+next[k][0];
			ny=q.front().y+next[k][1];
			if(nx<0||nx>r-1||ny<0||ny>c-1)
			  continue;
			if((mp[nx][ny]=='.'||mp[nx][ny]=='J')&&bookf[nx][ny]==-1)//火可以通过‘J’和‘.’
			{
				a.x=nx;
				a.y=ny;
				q.push(a);//如果符合条件则入队
				bookf[nx][ny]=bookf[q.front().x][q.front().y]+1;//火向周围扩散
			}
		}
		q.pop();//每扩完一次后父亲节点出队
	}
}
void bfsj()
{
	queue<node >q;
	node a;
	int nx,ny;
	int next[4][2]={{1,0},{0,1},{-1,0},{0,-1}};//四个方向
	for(int i=0;i<r;i++)
	{
	  for(int j=0;j<c;j++)
	    if(mp[i][j]=='J')
	    {
	    	bookj[i][j]=0;
	    	a.x=i;
	    	a.y=j;
	    	q.push(a);//J入队
		}
	  if(q.empty()==0)
		break;
	}
	while(q.empty()!=1)
	{
		if(q.front().x==0||q.front().x==r-1||q.front().y==0||q.front().y==c-1)//必须用front,因为一次可能入队多个节点,不一定能遍历所有节点,我因为这个一直WA
		{
			ans=bookj[q.front().x][q.front().y]+1;//最后逃出去的步数+1
			return;//符合条件提前结束
		}
		for(int k=0;k<=3;k++)
		{
		  nx=q.front().x+next[k][0];
		  ny=q.front().y+next[k][1];
		  if(nx<0||nx>r-1||ny<0||ny>c-1)
			continue;	
		  if(mp[nx][ny]=='.'&&bookj[nx][ny]==-1)
		  {
		    bookj[nx][ny]=bookj[q.front().x][q.front().y]+1;
		    if((bookj[nx][ny]<bookf[nx][ny])||(bookf[nx][ny]==-1))//两种情况:一种是joe的步数小于火,另一种是火==-1,即火烧不到这里,WA点
		    {
		      a.x=nx;
		      a.y=ny;
			  q.push(a); 
			}
		  }
	    }
	    q.pop();//不要忘记父亲节点出队
	}
	return;
}
发布了34 篇原创文章 · 获赞 0 · 访问量 803

猜你喜欢

转载自blog.csdn.net/aezakmias/article/details/104566366
今日推荐