J:代表Joe F:代表着火点(可能有多个) #:墙(障碍格)
这道题是帮助Joe走出一个大火蔓延的迷宫。Joe每分钟可以走到上下左右4个方向的相邻格之一,而所有着火的格子都会往四周蔓延(即如果某个空格与着火格有公共边,则下一分钟这个空格将着火)。迷宫中有一些障碍格,Joe和火都无法进入。求Joe走出这个迷宫的最短时间(分钟)。
这个题算是基本的广搜题吧!我想下它跟我们见过的最最基本的广搜有什么区别?是不是就是多了几个火源,而火源的作用是什么,是不是就是在蔓延的时候把一些能走的点变成不能走了,既然火源的速度和人一样,利用两个队列,一个储存人的状态,一个储存火的状态,把着火的点用fire的二维数组标记,首先将数据给出的着火点在fire数组中标记,然后每过一分钟,人先走一步(不能走着火点与障碍点,记录下步数),然后所有的着火点往四周(上下左右)拓展(不能拓展障碍点),如果人能顺利走出矩阵,则输出步数,否则输出IMPOSSIBLE。代码如下:
#include<stdio.h>
#include<queue>
#include<string.h>
using namespace std;
int R,C;
char map[1010][1010];
int vis[1010][1010];
int fire[1010][1010];
int d[4][2]={1,0,0,1,-1,0,0,-1}; //上下左右四个方向
struct node{
int x,y;
int time;
}; //人的状态
struct node1{
int x,y;
}; //火的状态
queue<node1>f; //储存火状态的队列
int Bfs(int x,int y){
int i,j;
memset(vis,0,sizeof(vis));
vis[x][y]=1;
queue<node>q; //储存人状态的队列
node s,e;
node1 b,c;
s.x=x;
s.y=y;
s.time=0;
q.push(s);
while(!q.empty()){
int cnt=q.size();//每次更新一层(就是当前队列中的所有状态都更新,注意是当前,不能直
//接用i<q.size(),因为正在往队列中添加新的状态,而新的状态是下一次再更新)
for(i=0;i<cnt;i++){ //人的状态的更新
s=q.front();
q.pop();
if(fire[s.x][s.y])continue; //着火点不能走
for(j=0;j<4;j++){
int xx=s.x+d[j][0];
int yy=s.y+d[j][1];
if(xx<0||yy<0||xx>=R||yy>=C) //逃出迷宫(矩阵),注意时间要加一
return s.time+1;
if(map[xx][yy]=='#')continue; //障碍点不能走
if(fire[xx][yy])continue; //着火点不能走
if(vis[xx][yy])continue; //已走过的点不能走
vis[xx][yy]=1;
e.x=xx;
e.y=yy;
e.time=s.time+1;
q.push(e);
}
}
cnt=f.size(); //每次更新一层(与人的状态的更新相同)
for(i=0;i<cnt;i++){ //火的状态的更新
b=f.front();
f.pop();
for(j=0;j<4;j++){
int xx=b.x+d[j][0];
int yy=b.y+d[j][1];
if(xx<0||yy<0||xx>=R||yy>=C)
continue; //越界
if(map[xx][yy]=='#')continue; //障碍点
if(fire[xx][yy])continue; //已经是着火点
fire[xx][yy]=1;
c.x=xx;
c.y=yy;
f.push(c);
}
}
}
return -1; //走不出迷宫(矩阵)
}
int main()
{
int T,i,j,x,y;
scanf("%d",&T);
while(T--){
scanf("%d %d",&R,&C);
memset(fire,0,sizeof(fire));
for(i=0;i<R;i++)
{
scanf("%s",map[i]);
}
while(!f.empty()){
f.pop();
}
for(i=0;i<R;i++){
for(j=0;j<C;j++){
if(map[i][j]=='J'){ //Joe开始所在的地方
x=i;
y=j;
}
else if(map[i][j]=='F'){ //初始化所有着火点
node1 a;
a.x=i;
a.y=j;
fire[i][j]=1;
f.push(a);
}
}
}
int ans=Bfs(x,y);
if(ans==-1)printf("IMPOSSIBLE\n");
else printf("%d\n",ans);
}
return 0;
}
另:这个题目有很多方法,如果你想的话 还可以先处理火源,把每个点最早到达的火源的时间记录下来,用所有的火源把地图处理完了之后再跑广搜。
今天是中秋节,没回家,在学校,准备把这开学几周欠下的东西都弄一下,虽未与家人团聚吃月饼,但仍有代码相伴不寂寞。(文采依旧)