题目描述
乔在迷宫中工作。不幸的是,迷宫的一部分着火了,迷宫的主人没有制定火灾的逃跑计划。请帮助乔逃离迷宫。根据乔在迷宫中的位置以及迷宫的哪个方块着火,你必须确定火焰烧到他之前,乔是否可以离开迷宫,如果能离开他能跑多快。
乔和火每分钟移动一个方格,上、下、左、右,四个方向中的一个。火势向四个方向同时蔓延。乔可以从迷宫的任何一个边界逃离迷宫。无论是乔还是火都不会到达有墙的位置。
输入 第一行输入包含一个整数,即测试次数 每个测试用例的第一行包含两个 整数R和C,用空格分隔,1≤R,C≤1000
下面R行中,每一行都包含C个字符,以及每个字符是以下之一:
#代表墙 . 代表空地,火和乔是可通行的 J 乔在迷宫中最初的位置,火和乔是可通行的 F 代表火 在每组测试中只有一个J 输出 对于每个测试用例,如果在火蔓延的时候烧到了乔,则乔无法逃出迷宫,输出’IMPOSSIBLE’如果乔能逃出迷宫,则输出乔最快可以在几分钟内安全逃出迷宫,每组输出占一行#### #JF# #..# #..# 3 3 ### #J. #.F 样例输出 3 IMPOSSIBLE
思路如下
- 题意:有 好多堆 🔥,问能不能在火烧到人之间,顺利逃出迷宫
- 思路:我们可以用一个专门的书组统计 🔥 到达某个位置所需的最短时间,但是我们会想可能有 好多堆 🔥,那么怎对 🔥 应用编写一个bfs_fire() 呢? ,其实应用 也很简单,就是一次性把所有 🔥 的初始位置全部压入 队列 q,就行了,然后在不断更新 🔥 到达某个位置所需的最小时间(具体看代码);然后我们可以考虑对 “🏃人” 编写一个bfs_man(),有一个地方需要理解就是 : 人怎么才能安全的到达某个位置 ???,显然 人到达该位置的时间只要 小于
所有🔥到达该位置所需的最小时间
,就可安全到达该位置,而“所有🔥到达该位置所需的最小时间”已经在调用 bfs_fire() 的时候被计算出来了,最后再补充:人只要赶在🔥之前先到达边界就可以安全逃生了 。————(剩下不懂的具体看代码吧)
题解如下
wa了十几发终于做出来了
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
const int Len = 1005;
char map[Len][Len];
int mov[4][2] = { {1,0},{0,1},{-1,0},{0,-1}};
int tim[Len][Len]; //火到达(i , j)位置所需要最短的时间是 tim[i][j]
int mark[Len][Len]; //标记人是否走过某个位置
vector<pair<int , int > > pir; //pir用来存储所有🔥初始位置的坐标
int m,n;
int x,y; /* 人的坐标 */
struct Node
{
int x,y,t;
}st,ed;
queue<Node> q;
//火专用
void bfs_fire()
{
//初始化
for(int i = 0; i < m; i ++)
for(int j = 0; j < n; j ++)
tim[i][j] = 1e9;
while(pir.size() > 0) //把所有🔥的初始位置压入队列进行处理
{
st.x = pir.back().first;
st.y = pir.back().second;
st.t = 0;
tim[st.x][st.y] = 0;
q.push(st);
pir.pop_back();
}
while(! q.empty())
{
st = q.front();
q.pop();
for(int i = 0; i < 4; i ++)
{
ed.x = st.x + mov[i][0];
ed.y = st.y + mov[i][1];
ed.t = st.t + 1;
if(ed.x >= 0 && ed.y >= 0 && ed.x < m && ed.y < n && map[ed.x][ed.y] != '#' && tim[ed.x][ed.y] > ed.t)
{
tim[ed.x][ed.y] = ed.t; //更改到达(ed.x , ed.y)位置所需要的最小时间为:ed.t;
q.push(ed);
}
}
}
}
int min_time;
//人专用
bool bfs_man()
{
bool flag = 0;
//各种初始化、赋值、做标记、压队列
min_time = 1e9;
memset(mark , 0 , sizeof(mark));
st.x = x;
st.y = y;
st.t = 0;
mark[st.x][st.y] = 1;
q.push(st);
while(! q.empty())
{
st = q.front();
q.pop();
if(st.x == 0 || st.y == 0 || st.x == m - 1 || st.y == n - 1)
{
flag = 1;
min_time = min(min_time , st.t);
continue;
}
for(int i = 0; i < 4; i ++)
{
ed.x = st.x + mov[i][0];
ed.y = st.y + mov[i][1];
ed.t = st.t + 1;
if(ed.x >= 0 && ed.y >= 0 && ed.x < m && ed.y < n && map[ed.x][ed.y] != '#' && mark[ed.x][ed.y] == 0 && ed.t < tim[ed.x][ed.y]) /* ed.t < tim[ed.x][ed.y] 表明 人到达(ed.x , ed.y) 所需时间ed.t 只有小于🔥到达该位置所需要的最小时间tim[ed.x][ed.y] 人才可以安全的走到这个位置 */
{
mark[ed.x][ed.y] = 1;
q.push(ed);
}
}
}
return flag;
}
int main()
{
//freopen("test.txt","r",stdin);
int t;
scanf("%d", &t);
while(t --)
{
scanf("%d %d ", &m, &n);
pair<int , int> pirr;
for(int i = 0; i < m; i ++)
{
for(int j = 0; j < n; j ++)
{
scanf("%c", &map[i][j]);
if(map[i][j] == 'J')
{
x = i,y = j;
}
else if(map[i][j] == 'F')
{
pirr.first = i;
pirr.second = j;
pir.push_back(pirr);
}
}
getchar();
}
bfs_fire();
if(bfs_man())
{
printf("%d\n",min_time + 1);
}
else
printf("IMPOSSIBLE\n");
}
return 0;
}