Problem 2196 EscapeAccept: 173 Submit: 1030
Time Limit: 1000 mSec Memory Limit : 32768 KB
Problem Description
小明进入地下迷宫寻找宝藏,找到宝藏后却发生地震,迷宫各处产生岩浆,小明急忙向出口处逃跑。如果丢下宝藏,小明就能迅速离开迷宫,但小明并不想轻易放弃自己的辛苦所得。所以他急忙联系当程序员的朋友你(当然是用手机联系),并告诉你他所面临的情况,希望你能告诉他是否能成功带着宝藏逃脱。
Input
有多组测试数据。
每组测试数据第一行是一个整数T,代表接下去的例子数。(0<=T<=10)
接下来是T组例子。
每组例子第一行是两个整数N和M。代表迷宫的大小有N行M列(0<=N,M<=1000)。
接下来是一个N*M的迷宫描述。
S代表小明的所在地。
E代表出口,出口只有一个。
.代表可以行走的地方。
!代表岩浆的产生地。(这样的地方会有多个,其个数小于等于10000)
#代表迷宫中的墙,其不仅能阻挡小明前进也能阻挡岩浆的蔓延。
小明携带者宝藏每秒只能向周围移动一格,小明不能碰触到岩浆(小明不能和岩浆处在同一格)。
岩浆每秒会向四周不是墙的地方蔓延一格。
小明先移动完成后,岩浆才会蔓延到对应的格子里。
小明能移动到出口,则小明顺利逃脱。
Output
每组测试数据输出只有一行“Yes”或者“No”。 “Yes”代表小明可以成功逃脱。否则输出“No”。
Sample Input
3
5 5
....!
S....
#....
!#...
#E...
2 2
S.
!E
2 2
SE
!.
Sample Output
Yes
No
Yes
Source
福州大学第十二届程序设计竞赛
思路来源:FZU 1408 位图【通过1找0的BFS、当然是多个1】、我们这里可以模仿这个题的做法,把所有!(岩浆源)看成1,然后遍历所有能走的点,标记上走到那里的时间。
解题思路:
分成两部分的BFS,第一部分用于处理!,标记上!到图上能够蔓延到的点的时间:
void bfsyu()
{
while(!s.empty())//在输入图的时候入队所有!
{
now=s.front();
yanjiang[now.x][now.y]=now.output;//标记上时间
s.pop();
for(int i=0;i<4;i++)
{
nex.x=now.x+fx[i];
nex.y=now.y+fy[i];
if(nex.x>=0&&nex.x<n&&nex.y>=0&&nex.y<m&&vis[nex.x][nex.y]==0&&a[nex.x][nex.y]!='#')//在边界范围内,并且能够走到的地方
{
nex.output=now.output+1;
vis[nex.x][nex.y]=1;
s.push(nex);
}
}
}
return ;
}第二部分BFS,用于处理S到E
void bfs(int x,int y)
{
memset(vis,0,sizeof(vis));
while(!s.empty())
{
s.pop();
}
now.x=x;
now.y=y;
now.output=0;
s.push(now);//push进去起点
while(!s.empty())
{
now=s.front();
s.pop();
for(int i=0;i<4;i++)
{
nex.x=now.x+fx[i];
nex.y=now.y+fy[i];
if(nex.x>=0&&nex.x<n&&nex.y>=0&&nex.y<m&&a[nex.x][nex.y]!='#'&&a[nex.x][nex.y]!='!'&&vis[nex.x][nex.y]==0)//如果能走,并且没有走过
{
if(a[nex.x][nex.y]=='E' && yanjiang[nex.x][nex.y]>=now.output+1)//如果走到的是终点并且人和岩浆同时到达终点,也算是可以逃脱,这里特判
{
printf("Yes\n");
return ;
}
if(yanjiang[nex.x][nex.y]!=-1)//正常走
{
if(yanjiang[nex.x][nex.y]>now.output+1)//这块注意不能加等号了、在到达终点前,人和岩浆不可以一起到达一个地方。
{
nex.output=now.output+1;
s.push(nex);
vis[nex.x][nex.y]=1;
}
}
else//如果是岩浆无法走到的点,但是人可以走的到,也要走下去
{
nex.output=now.output+1;
s.push(nex);
vis[nex.x][nex.y]=1;
}
}
}
}
printf("No\n");
return ;
}完整AC代码:
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
int n,m;
struct zuobiao
{
int x,y,output;
}now,nex;
char a[1002][1002];
int vis[1002][1002];
int yanjiang[1002][1002];
int fx[4]={0,0,1,-1};
int fy[4]={-1,1,0,0};
queue<zuobiao >s;
void bfsyu()
{
while(!s.empty())
{
now=s.front();
yanjiang[now.x][now.y]=now.output;
s.pop();
for(int i=0;i<4;i++)
{
nex.x=now.x+fx[i];
nex.y=now.y+fy[i];
if(nex.x>=0&&nex.x<n&&nex.y>=0&&nex.y<m&&vis[nex.x][nex.y]==0&&a[nex.x][nex.y]!='#')
{
nex.output=now.output+1;
vis[nex.x][nex.y]=1;
s.push(nex);
}
}
}
return ;
}
void bfs(int x,int y)
{
memset(vis,0,sizeof(vis));
while(!s.empty())
{
s.pop();
}
now.x=x;
now.y=y;
now.output=0;
s.push(now);
while(!s.empty())
{
now=s.front();
s.pop();
for(int i=0;i<4;i++)
{
nex.x=now.x+fx[i];
nex.y=now.y+fy[i];
if(nex.x>=0&&nex.x<n&&nex.y>=0&&nex.y<m&&a[nex.x][nex.y]!='#'&&a[nex.x][nex.y]!='!'&&vis[nex.x][nex.y]==0)
{
if(a[nex.x][nex.y]=='E' && yanjiang[nex.x][nex.y]>=now.output+1)
{
printf("Yes\n");
return ;
}
if(yanjiang[nex.x][nex.y]!=-1)
{
if(yanjiang[nex.x][nex.y]>now.output+1)
{
nex.output=now.output+1;
s.push(nex);
vis[nex.x][nex.y]=1;
}
}
else
{
nex.output=now.output+1;
s.push(nex);
vis[nex.x][nex.y]=1;
}
}
}
}
printf("No\n");
return ;
}
int main()
{
int t;
while(~scanf("%d",&t))
{
while(t--)
{
while(!s.empty())
{
s.pop();
}
memset(yanjiang,-1,sizeof(yanjiang));
memset(vis,0,sizeof(vis));
int x,y;
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
{
scanf("%s",a[i]);
for(int j=0;j<m;j++)
{
if(a[i][j]=='S')
{
x=i;
y=j;
}
if(a[i][j]=='!')
{
now.x=i;
now.y=j;
now.output=0;
s.push(now);
yanjiang[now.x][now.y]=0;
vis[now.x][now.y]=1;
}
}
}
bfsyu();
bfs(x,y);
}
}
}
/*
3
6 6
E.S..#
####.#
.....#
.#####
......
######
2 3
S.E
!..
*/
本文介绍了一个迷宫逃脱问题的算法解决方案。该方案采用两阶段BFS算法,首先标记岩浆蔓延范围,接着计算人物能否在岩浆到达之前逃至出口。文章提供了完整的代码实现。
5629

被折叠的 条评论
为什么被折叠?



