题目:
小明最后也没能进入游戏大厂,也没能娶到心爱的女孩,现在小明在一家迷宫里工作。 不幸的是,迷宫里因为线路老化而发生了火灾。小明现在需要一个逃跑路线,请你帮助倒霉的小明从迷宫中逃离出去吧 小明在迷宫中编号为 J 的位置,根据小明在迷宫中的位置以及迷宫中着火的位置(F),你必须确定在火焰烧到小明之前,他是否能逃离迷宫,如果能,他能多快逃离。 小明每分钟移动一个方格(上、下、左、右四个方向中的一个),但是火焰一分钟能向四个方向同时蔓延。小明可以从迷宫的任何一个边界逃离。无论是小明还是火都不会到达有墙的位置。。
输入:
输入的第一行包含一个整数,即测试数 每个测试用例的第一行包含两个整数R和C,用空格分隔,1≤ R、 C≤ 1000 以下R行中的每一行都包含C个字符,每个字符都是以下字符之一: #,一堵墙 .,空地,小明和火都可以通过 J,小明在迷宫中的初始位置 F,着火的广场 每个测试用例中只有一个J。
输出:
对于每个测试用例,如果小明不能在火烧到之前退出迷宫,则输出一行 “IMPOSSIBLE” 如果能逃出迷宫,则输出小明最快可以在几分钟内安全的逃出迷宫,每组输出占一行
思路:主要利用广搜的思想,将火的每一轮扩散加入队列,再判断人能走的位置,将可以走的位置加入队列,如果人走的位置最终可以越出输出范围,即视为逃脱成功。注意一点,火应该优先于人,才可以判断人之后可以走的路程,一定先将火的数据加入队列,再判断人是否可以逃脱。
代码:
#include<bits/stdc++.h>
using namespace std;
int sx,sy;
struct node
{
int x,y,step;
int flag;
}sc;
queue<node> q;
int dir[4][2]={0,1,0,-1,1,0,-1,0};
int book[1005][1005];//记录人走的
char mp[1005][1005];//地图
int n,m;
int bfs()
{
node head,next;
memset(book,0,sizeof(book));//多组输入记得每组数据清零
sc.x=sx;//把人的数据加入队列
sc.y=sy;
sc.step=0;
sc.flag=0;
q.push(sc);
while(!q.empty())
{
head=q.front();
q.pop();
if(head.flag==1)//将火扩散的情况加入队列
{
for(int i=0;i<4;i++)
{
int tx=head.x+dir[i][0];
int ty=head.y+dir[i][1];
if(tx<0||tx>=n||ty<0||ty>=m||mp[tx][ty]=='#'||mp[tx][ty]=='F')
continue;
mp[tx][ty]='F';
next.x=tx;
next.y=ty;
next.step=head.step+1;
next.flag=1;
q.push(next);
}
}
else//将人能走的位置加入队列
{
for(int i=0;i<4;i++)
{
int tx=head.x+dir[i][0];
int ty=head.y+dir[i][1];
if(tx<0||tx>=n||ty<0||ty>=m)
{
return head.step+1;
}
if(mp[tx][ty]=='#'||mp[tx][ty]=='F'||book[tx][ty])
continue;
book[tx][ty]=1;
next.x=tx;
next.y=ty;
next.flag=0;
next.step=head.step+1;
q.push(next);
}
}
}
return 0;
}
int main()
{
int t;
cin>>t;
while(t--)
{
while(!q.empty())//清空队列
q.pop();
memset(book,0,sizeof(book));
cin>>n>>m;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
cin>>mp[i][j];
if(mp[i][j]=='J')
{
sx=i;
sy=j;
}
if(mp[i][j]=='F')
{
sc.x=i;
sc.y=j;
sc.step=0;
sc.flag=1;
q.push(sc);
}
}
int ans=bfs();
if(ans)
cout<<ans<<endl;
else
cout<<"IMPOSSIBLE"<<endl;
}
}
题目本身不难,但数据量有点大,要对每一个细节检查到位(对自己说的,别介)。