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

问题连接

问题描述

Joe在迷宫里工作,不幸迷宫里有些地方着火了,Joe每次每分钟能从他的位置纵向或横向移动到下一个方格区域,但有火和墙的地方不能走。火焰也是每分钟向四周扩散到下一个区域,但也会被墙阻挡。问Joe能不能逃出迷宫,如果能,则输出逃生所要用的最短时间,否则输出"IMPOSSIBLE".

问题分析

time_f[i][j]表示(i,j)这个位置开始有火的时间
time_j[i][j]表示joe到达(i,j)这个位置要花的最短时间
先找到起始地图上的火焰,都放入队列中,因为火焰可能不止一个,然后就是常规的BFS,对time_f数组赋值,就得到了任意一点处火焰出现的时间。
先找到’J’的位置,然后放入队列中,进行BFS,通过方向动作得到相邻点的坐标,如果走到这一点就跑出迷宫,根据BFS的特点,那么这一点就是花时间最少的点,输出并return结束;如果走到这点的是墙或者已经有火了或者之前走过了或者通过其它路径可以更快到,那么不能走;否则可以走,放入队列。当队列中所有值都弹出来了但还没有出迷宫,说明已经无路可走了,根据题意输出"IMPOSSIBLE"

程序如下

#include<iostream>
#include<queue>
#include<cstdio>
#include<cstring>
using namespace std;
const int N = 1005;

struct state
{
	int y, x, time;
}q, p;
int r, c;
char map[N][N];//地图 
int time_f[N][N];//火的时间打表 
int time_j[N][N];//joe的时间打表 
int dir[4][2] = { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 } };//方向 

void bfs_f();//对火焰用BFS 
void bfs_j();//对Joe用BFS 

int main()
{
	int i, t;
	scanf("%d", &t);
	while (t--)
	{
		scanf("%d %d", &r, &c);
		for (i = 0; i < r; i++)
			scanf("%s",map[i]);//输入地图 
		bfs_f();
		bfs_j();
	}
	return 0;
}

void bfs_f()//对火打表
{
	int i, j;
	queue<state>Q;
	memset(time_f, 0x3f, sizeof(time_f));//初始化为0x3f3f3f3f
	q.time = 0;
	for (i = 0; i < r; i++)//找'F'并加入队列,注意'F'可能不止一个 
		for (j = 0; j < c; j++)
			if (map[i][j] == 'F')
			{
				q.y = i;
				q.x = j;
				Q.push(q);
				time_f[i][j] = 0;
			}
	while (!Q.empty())
	{
		q = Q.front();
		Q.pop();
		for (i = 0; i < 4; i++)
		{
			p.y = q.y + dir[i][0];
			p.x = q.x + dir[i][1];
			p.time = q.time + 1;
			//位置合理,时间合理
            if (p.x >= 0 && p.x < c&&p.y >= 0 && p.y < r&&p.time < time_f[p.y][p.x] && map[p.y][p.x] != '#')
			{
				time_f[p.y][p.x] = p.time;//打表
				Q.push(p);
			}
		}
	}
}
void bfs_j()//对joe进行BFS
{
	bool flag = 1;
	int i, j;
	queue<state>Q;
	memset(time_j, 0x3f, sizeof(time_j));
	for (i = 0; i < r; i++)//找到'J'
	{
		if (flag)//跳出循环的判断 
		for (j = 0; j < c; j++)
		{
			if (map[i][j] == 'J')
			{
				q.y = i;
				q.x = j;
				q.time = 0;
				Q.push(q);
				time_j[i][j] = 0;
				flag = 0;
				break;
			}
		}
		else break;
	}
	while (!Q.empty())
	{
		q = Q.front();
		Q.pop();
		p.time = q.time + 1;//时间
		for (i = 0; i < 4; i++)
		{
			p.y = q.y + dir[i][0];
			p.x = q.x + dir[i][1];
			if (p.x < 0 || p.x >= c || p.y < 0 || p.y >= r)//跑出迷宫
			{
				printf("%d\n", p.time);
				return;
			}
			//位置合理,时间合理
			if (p.time < time_j[p.y][p.x] && p.time < time_f[p.y][p.x] && map[p.y][p.x] != '#')
			{
				time_j[p.y][p.x] = p.time;
				Q.push(p);
			}
		}
	}
	printf("IMPOSSIBLE\n");
}

两个BFS的整合版

#include<iostream>
#include<queue>
#include<cstdio>
#include<cstring>
using namespace std;
const int N = 1005;

struct state
{
	int y, x, time;
}q, p;
int r, c;
char map[N][N];//地图 
int time_f[N][N];//火的时间打表 
int time_j[N][N];//joe的时间打表 
int dir[4][2] = { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 } };//方向 

void bfs();
bool deal(bool flag,queue<state>&);//容器作参数

int main()
{
	int i, t;
	scanf("%d", &t);
	while (t--)
	{
		scanf("%d %d", &r, &c);
		for (i = 0; i < r; i++)
			scanf("%s",map[i]);//输入地图 
		bfs(); 
	}
	return 0;
}

void bfs()
{
	queue<state>Q;
	queue<state>F;
	memset(time_f, 0x3f, sizeof(time_f));//初始化为0x3f3f3f3f
	memset(time_j, 0x3f, sizeof(time_j));
	q.time = 0;
	for (int i = 0; i < r; i++)
	for (int j = 0; j < c; j++)
	{
		if (map[i][j] == 'F')//找'F'并加入队列
		{
			q.y = i;
			q.x = j;
			F.push(q);
			time_f[i][j] = 0;
		}
		else if (map[i][j] == 'J')
		{
			q.y = i;
			q.x = j;
			Q.push(q);
			time_j[i][j] = 0;
		}
	}
	deal(0, F);
	bool flag = deal(1, Q);
	if (!flag) printf("IMPOSSIBLE\n");
}
bool deal(bool flag, queue<state>&M)//flag为标记,如果是0,则按bfs_f处理,否则否则按bfs_j处理
{
	while (!M.empty())
	{
		q = M.front();
		M.pop();
		for (int i = 0; i < 4; i++)
		{
			bool judge;
			p.y = q.y + dir[i][0];
			p.x = q.x + dir[i][1];
			p.time = q.time + 1;
			if (!flag) judge = (p.x >= 0 && p.x < c&&p.y >= 0 && p.y < r&&p.time < time_f[p.y][p.x] && map[p.y][p.x] != '#');
			else
			{
				if (p.x < 0 || p.x >= c || p.y < 0 || p.y >= r)//跑出迷宫
				{
					printf("%d\n", p.time);
					return 1;
				}
				judge = (p.time < time_j[p.y][p.x] && p.time < time_f[p.y][p.x] && map[p.y][p.x] != '#');
			}
			if (judge)//位置合理,时间合理
			{
				time_f[p.y][p.x] = p.time;//打表
				M.push(p);
			}
		}
	}
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值