I—Fire(多个bfs搜索)
Fire(多个bfs搜索)
题意:Joe被困在迷宫中,可以从边界逃出,但迷宫中有火,火和Joe同时移动,问Joe能否逃出迷宫。
解题思路:
该题看起来很困难,因为我们可能会想到两个bfs搜索同时进行,
如果这样就不知道从何处理了。因为这相当于两条盲驴乱撞,很难求出结果。
那么,我们是否可以先进行一个再进行另一个呢?
显然是可以的,因为我们关键是要让Joe逃出迷宫,如果我是预言家,我先前就知道了火到达迷宫中各个点的时间,那么火和Joe同时烧,Joe不就可以根据火等等种种因素来判断行径吗?
所以,我们可以设置一个二维数组存储每个点火烧到的时间,当然,对于无法烧到的点我们设置其时间为无穷大
int times[maxn][maxn];
那么,通过对火bfs搜索记录每个点火烧到的时间,再通过这个去判断Joe能不能被火烧到,即Joe走到某点的时间如果小于times[x][y]
那么说明不会被烧到。OK,以此对Joe进行一趟bfs搜索。则易解。
PS:一定一定要清空队列,一定一定要初始化数组,还有最重要的一点:火种不只是只有一个,可能有多个火种,即我们要进行多源点bfs搜索。
AC代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<string>
#include<stack>
#include<queue>
#include<cstring>
#include<memory.h>
#include<map>
#include<iterator>
#include<list>
#include<set>
#include<functional>
using namespace std;
const int maxn=1002; //迷宫的最大尺寸。
const int INF=0x3f3f3f3f;//表示无穷大
char maze[maxn][maxn];//迷宫
bool visited[maxn][maxn];
int go[4][2]={{1,0},{0,1},{-1,0},{0,-1}};//代表操作行为。
int t,r,c;//t组测试用例,迷宫大小为r*c;
typedef struct node{
int x,y;//当前状态Joe的坐标
int step;//走到当前状态所消耗的时间
}node;
int times[maxn][maxn];//火燃烧到该点所需要消耗的时间。
queue<node> q1;
node fire,temp;
bool check_fire(int x,int y){
//判断该点能否烧
if(x>=0&&y>=0&&x<r&&y<c&&maze[x][y]!='#')
return true;
else return false;
}
int bfs_fire(){
//先对火进行bfs搜索,记录燃烧到没点所需的时间,以便Joe做出选择。
while(!q1.empty()){
fire=q1.front();
q1.pop();
for(int i=0;i<4;i++){
temp.x=fire.x+go[i][0];
temp.y=fire.y+go[i][1];
if(check_fire(temp.x,temp.y)&×[temp.x][temp.y]>times[fire.x][fire.y]+1){
//times[temp.x][temp.y]>times[fire.x][fire.y]+1 这个是为了找到烧到该点的最短时间。
temp.step=fire.step+1;//火燃烧到此状态的时间。
times[temp.x][temp.y]=times[fire.x][fire.y]+1;
//存储此状态。
q1.push(temp);
}
}
}
return 0;
}
bool check_joe(node temp){
//检查Joe此点是否可走。
if(!visited[temp.x][temp.y]&&temp.x>=0&&temp.y>=0&&temp.x<r&&temp.y<c&&maze[temp.x][temp.y]!='#')
return true;
else return false;
}
int bfs_Joe(node joe){
queue<node> q2;
q2.push(joe);
visited[joe.x][joe.y]=true;
while(!q2.empty()){
joe=q2.front();
q2.pop();
if(joe.x==0||joe.x==r-1||joe.y==0||joe.y==c-1){
//判断此时Joe是否逃出迷宫,到了边界再走一步就可逃出来了,可别忘了哦
cout<<joe.step+1<<endl;
return 0;
}
for(int i=0;i<4;i++){
temp.x=joe.x+go[i][0];
temp.y=joe.y+go[i][1];
if(check_joe(temp)&&joe.step+1<times[temp.x][temp.y]){
visited[temp.x][temp.y]=true;
temp.step=joe.step+1;
q2.push(temp);
}
}
}
printf("IMPOSSIBLE\n");
return 0;
}
int main(){
node joe;
while(scanf("%d",&t)!=EOF){
while(t--){
memset(times,INF,sizeof(times));//初始化,设一开始烧到每个点的时间都是无穷大,因为有的点是烧不到的。
scanf("%d%d",&r,&c);
for(int i=0;i<r;i++){
scanf("%s",maze[i]);
for(int j=0;j<c;j++){
if(maze[i][j]=='J'){
joe.x=i;joe.y=j;joe.step=0;
//寻找Joe的位置
}
else if(maze[i][j]=='F'){
fire.x=i;fire.y=j;
times[i][j]=0;
//将火种入队
q1.push(fire);
}
}
}
bfs_fire();
memset(visited,false,sizeof(visited));
//重置辅助数组,供Joe判断。
bfs_Joe(joe);
}
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!