搜索--广度搜索--J - Fire! (双bfs())

本文介绍了一个迷宫逃脱问题的解决方案,通过两个广度优先搜索(BFS)算法来模拟人物(Joe)与火势的移动,确保人物能尽快安全逃离迷宫。文章详细解释了算法流程与注意事项。

题目:

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

 IMPOSSIBL

题目:

 

     J要逃离着火的森林,J和火都只能往上下左右四个方向转移,J到达边界即可离开。求最小的逃离步数,不能的话输出IMPOSSIBL。不过值一提的是,题目要求着火的位置并不唯一(一是因为portions。此外,题目说的是,there will be exactly one J in each test case,但是并没有说F),需要特别注意一下。

思路:

    两个bfs()处理即可,不过要先处理着火的函数,因为要提前算出火到达每个地方的时间(times[][]数组),这样才能让J在走的时候,有选择性。

注意:

   1.前面已经提到,第一个要注意的地方就是着火点不唯一。

  2.因为队列q定义的是全局变量,有T组数据,所以每次读入新的数据前都要清空一次。(vis[][]一样)

  3.还有在看解析的时候,发现一种初始化结构体的函数。以后也可以尝试使用:

      

typedef struct node
{
	int r;
	int c;
	int step;
	node(int r1,int c1,int step1)
	{
		r=r1;
		c=c1;
		step=step1;
	}
	node(){}
	
 }node; 
//使用的时候,不用定义一个结构体,三个变量即可,如下: 
int R,C,STEP;
 for(i=0;i<4;i++)
        {
            R=temp.r+dr[i];
            C=temp.c+dc[i];
            STEP=temp.step+1;
            if(R>=0&&R<r&&C>=0&&C<c&&(Map[R][C]=='.'||Map[R][C]=='J')&&visit[R][C]==0)
            {
                visit[R][C]=1;
                q.push(node(R,C,STEP));//传入这三个整数即可,和新定义一个结构体一样的意思。
                times[R][C]=STEP;
            }
        }

 

#include<bits/stdc++.h>
#define MAX 1100
#define  INF 0x3f3f3f3f

using namespace std;

typedef struct node
{
	int x;
	int y;
	int step;
}node;

node ss,tt,s,w;
int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
char cc[MAX][MAX];
int vis[MAX][MAX];
int times[MAX][MAX];
int t,r,c;
int numstep;
queue<node> q;

void bfs_f()
{
	while(!q.empty())
	{
		node first;
		first=q.front();
		q.pop();
		for(int i=0;i<4;i++)
		{
			s.x=first.x+dir[i][0];
			s.y=first.y+dir[i][1];
		        s.step=first.step+1;
			if(s.x>=0&&s.x<r&&s.y>=0&&s.y<c&&(cc[s.x][s.y]=='.'||cc[s.x][s.y]=='J')&&!vis[s.x][s.y])
			{
				vis[s.x][s.y]=1;
				q.push(s);
			        times[s.x][s.y]=s.step;
			}
		}
		
	}
}

int bfs_j()
{
//	cout<<"yes,it comes in----bfs_j()!"<<endl;
	q.push(ss);
	vis[ss.x][ss.y]=1;
	while(!q.empty())
	{
		node second;
		second=q.front();
		q.pop();
		if(second.x==0||second.x==r-1||second.y==0||second.y==c-1)
		{
			//cout<<"yes,it comes in------if()"<<endl;
			numstep=second.step+1;
			return 1;
			
		}
		for(int i=0;i<4;i++)
		{
			w.x=second.x+dir[i][0];
			w.y=second.y+dir[i][1];
			w.step=second.step+1;
			if(w.x>=0&&w.x<r&&w.y>=0&&w.y<c&&cc[w.x][w.y]=='.'&&vis[w.x][w.y]==0&&w.step<times[w.x][w.y])
			{
				vis[w.x][w.y]=1;
				q.push(w);
			}
		}
	}
	return 0;
	
}

int main()
{
	cin>>t;
	while(t--)
	{
		while(!q.empty())//每次进来,队列都得清空一次,因为会有多组数据,而队列定义的是全局的变量 
		{
			q.pop();
		}
		cin>>r>>c;
		for(int i=0;i<r;i++)
		{
			scanf("%s",&cc[i]);
			for(int j=0;j<c;j++)
			{
				if(cc[i][j]=='J')
				{
					ss.x=i;
					ss.y=j;
					ss.step=0;
				}
				if(cc[i][j]=='F')//这里应该注意,因为起火的位置不唯一 。为什么呢(一是因为portions。此外,题目说的是,there will be exactly one J in each test case,但是并没有说F) 
				{
					tt.x=i;
					tt.y=j;
					tt.step=0;
					q.push(tt);
					vis[i][j]=1;
					times[i][j]=0;
				}
			}
		}
		for(int i=0;i<r;i++)
		{
			for(int j=0;j<c;j++)
			{
				times[i][j]=INF;
			}
		}
		memset(vis,0,sizeof(vis));
		bfs_f();
		memset(vis,0,sizeof(vis));
		if(bfs_j())
		{
			cout<<numstep<<endl;
		}
		else
		  cout<<"IMPOSSIBLE"<<endl;
    }
    return 0;
}

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值