UVA - 11624 Fire! (kuangbin - 简单搜索)

本文介绍了如何解决UVA 11624题——“Fire!”。题目要求通过广度优先搜索(BFS)算法确定主角乔能否在火势蔓延到他之前逃离迷宫。乔和火每分钟移动一格,只能上下左右四个方向。分析中详细解释了双BFS的实现过程,包括如何分别记录火的蔓延和乔的移动路径,以及如何避免误判。最后,给出了关键代码片段。
摘要由CSDN通过智能技术生成

题目描述(已转换成中文)

  乔在迷宫中工作。不幸的是,迷宫的一部分着火了,迷宫的主人没有制定火灾的逃跑计划。请帮助乔逃离迷宫。根据乔在迷宫中的位置以及迷宫的哪个方块着火,你必须确定火焰烧到他之前,乔是否可以离开迷宫,如果能离开他能跑多快。
  乔和火每分钟移动一个方格,上、下、左、右,四个方向中的一个。火势向四个方向同时蔓延。乔可以从迷宫的任何一个边界逃离迷宫。无论是乔还是火都不会到达有墙的位置。

输入格式

  第一行输入包含一个整数,即测试次数,每个测试用例的第一行包含两个整数R和C,用空格分隔,1≤R,C≤1000
  下面R行中,每一行都包含C个字符,以及每个字符是以下之一:
  # 代表墙
  . 代表空地,火和乔是可通行的
  J 乔在迷宫中最初的位置,火和乔是可通行的
  F 代表火
  在每组测试中只有一个J

输出格式

  对于每个测试用例,如果在火蔓延的时候烧到了乔,则乔无法逃出迷宫,输出’IMPOSSIBLE’如果乔能逃出迷宫,则输出乔最快可以在几分钟内安全逃出迷宫,每组输出占一行

输入输出样例
输入

2
4 4

#JF#
#…#
#…#
3 3

#J.
#.F

输出

3
IMPOSSIBLE

题目链接

分析:

  这道题是需要进行双bfs,大致题意是人要在火还没烧到方格前经过方格,当他走到迷宫的边界的时候即视为逃出来了迷宫且不会被火烧,求人逃出迷宫所需的最少时间。首先读入测试次数,在读入每个方格具体的字符的时候,记录人所在的初始位置(p1, q1),因为人的初始位置只有一个,所以可以用两个变量记录其坐标,但火可能不止一堆,所以只能在后续的bfs1函数中记录。
  接着主函数调用bfs1函数,创建一个数据类型为node的队列来存放火烧过方格的坐标。因为有多组测试,所以在bfs1在处理各个坐标之前应该对vis1数组元素都初始化为-1,为什么要初始化为-1,而不是像之前一些bfs的题目直接清零?因为火有初始位置,没经过任何时间火就已经在方格里了,所以此时用于标记时间的vis1数组在此点应为0,如果我们把所有方格都初始化为0的话,火所在初始点的标记就比较麻烦,所以统一都初始化为-1,后续两个for循环遍历每个位置,对有火的位置才标记vis1[i][j] = 0,并且把初始点有火的坐标压入到队列,接着就是常规的bfs,利用队列更新vis1数组(火所能烧到的位置的最短时间),直到烧过能烧到的方格为止。
  同理,求人在逃出迷宫时所用的最短时间也是bfs的思想,bfs函数中也是常规的做法,利用队列实现vis2数组的更新(人所能到达的位置的最短时间),只不过在坐标node是否能压入队列的判断条件中还多了判断在人到达这个方格之前火有没有烧到过,当坐标已经到达迷宫边界的时候,返回vis[i][j] + 1;若队列已经为空,人还没走到迷宫边界,则返回-1(代表人走不出迷宫了)。

这道题需要注意的地方:

  在判断人到达某个方格时,火烧到过这个方格的判断条件应该是vis2[n.x][n.y] + 1 >= vis1[p][q] && vis1[p][q] != -1,vis1[p][q] != -1这个不能省略,我们已知vis1[p][q]的初始化为-1,如果在bfs1函数中vis1[p][q]没被更新过,则说明火根本没烧过这个方格,而此时人到了这个方格,vis2[n.x][n.y] + 1必定大于-1,此时判断条件是成立的,所以这个点会被误认为是人不能到达的,从而执行了continue,所以要&& vis1[p][q] != -1,代表此方格在人到达之前已经被火烧过,即人不能到达此方格。

代码如下:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int r, c, i, j, p, q, p1, q1;
char a[1005][1005]; 
int vis1[1005][1005], vis2[1005][1005];	//vis1数组代表火烧到这个方格所用的最短时间,vis2数组代表人走到这个方格所用的最短时间
int b[4][2] = {
   {
   0, 1}, {
   0, -1}, {
   1, 0}, {
   -1, 0}}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值