前言
暴力BFS打丑了...100分完美变身20分...
题目
一天, 一个画家在森林里写生,突然爆发了山洪,他需要尽快返回住所中,那里是安
全的。
森林的地图由R行C列组成,空白区域用点“.”表示,洪水的区域用“*”表示,而
岩石用“X”表示,另画家的住所用“D”表示,画家用“S”表示。
有以下几点需要说明:
1、 每一分钟画家能向四个方向移动一格(上、下、左、右)
2、 每一分钟洪水能蔓延到四个方向的相邻格子(空白区域)
3、 洪水和画家都不能通过岩石区域
4、 画家不能通过洪水区域(同时也不行,即画家不能移到某个格子,该格子在画家达到的同时被洪水蔓延到了,这也是不允许的)
5、 洪水蔓不到画家的住所。
给你森林的地图,编写程序输出最少需要花费多长时间才能从开始的位置赶回家中。
Input
输入第一行包含两个整数R和C(R,C<=50)。
接下来R行每行包含C个字符(“.”、“*”、“X”、“D”或“S”)。地图保证只有一个“D”和一个“S”。
Output
输出画家最快安全到达住所所需的时间,如果画家不可能安全回家则输出“KAKTUS”。
Sample Input
输入1: 3 3 D.* ... .S. 输入2: 3 3 D.* ... ..S 输入3: 3 6 D...*. .X.X.. ....S.
Sample Output
输出1: 3 输出2: KAKTUS 输出3: 6
分析
本来是正解,我料到了“有多个洪水源点”的情况,结果没想到数据中有很多“没有洪水”的情况....开心20分爆掉...
法一:两次暴力BFS,
第一次BFS洪水到达(i,j)的最早时间,BFS的时候先把每一层的节点扩展完,然后时间t++,再把扩展出的新点一起压进队列
第二次BFS画家到达(i,j)的最早时间
法二:也是两次暴力BFS,用数组记录到达的时间(直接比上一次+1,就不用扩展完再压队那么复杂了)
要点注意:
1.洪水的源点可能有不止一个
2.要考虑图中没有洪水的情况
法一代码
#include<cstdio>
#include<queue>
#include<vector>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN=50,INF=0x3f3f3f3f;
char a[MAXN+5][MAXN+5];
int dir1[5]={-1,0,1,0},dir2[5]={0,1,0,-1};
int f[MAXN+5][MAXN+5];//洪水到达(i,j)的最早时间
bool vis[MAXN+5][MAXN+5];
int n,m,ans=0x3f3f3f3f;
int sx,sy,tx,ty;
bool flag=false;
struct node
{
int x,y;
};
vector<node> water;
void bfs1()
{
//tmp用来暂存扩展出的新一层的点
queue<node> que,tmp;
int t=1;//开始时间定为1
node q,Tmp;
for(int i=0;i<water.size();i++)
{
f[water[i].x][water[i].y]=t;
que.push(water[i]);
}
while(!que.empty())
{
t++;
while(!que.empty())//每次扩展完一整层
{
q=que.front();
que.pop();
for(int i=0;i<4;i++)
{
int dx=q.x+dir1[i],dy=q.y+dir2[i];
if(f[dx][dy]==INF&&(a[dx][dy]=='.'||a[dx][dy]=='S'))
{
f[dx][dy]=t;
Tmp.x=dx,Tmp.y=dy;
tmp.push(Tmp);
}
}
}
while(!tmp.empty())
{
que.push(tmp.front());
tmp.pop();
}
}
}
void bfs2()
{
queue<node> que,tmp;
int t=1;//开始时间定为1
node q,Tmp;
q.x=sx,q.y=sy;
que.push(q);
while(!que.empty())
{
t++;
while(!que.empty())
{
q=que.front();
que.pop();
for(int i=0;i<4;i++)
{
int dx=q.x+dir1[i],dy=q.y+dir2[i];
//printf("x:%d y:%d t:%d\n",dx,dy,t);
if(a[dx][dy]=='.'&&t<f[dx][dy]&&!vis[dx][dy])
{
vis[dx][dy]=1;
Tmp.x=dx,Tmp.y=dy;
tmp.push(Tmp);
}
if(a[dx][dy]=='D')
{
flag=true;
ans=min(ans,t);
}
}
}
while(!tmp.empty())
{
que.push(tmp.front());
tmp.pop();
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%s",a[i]+1);
for(int j=1;j<=m;j++)
{
if(a[i][j]=='S')
sx=i,sy=j;
if(a[i][j]=='D')
tx=i,ty=j;
if(a[i][j]=='*')//好像没说洪水起点只有一个...
{
node tmp;
tmp.x=i,tmp.y=j;
water.push_back(tmp);
}
}
}
memset(f,INF,sizeof(f));
bfs1();
bfs2();
if(flag)
printf("%d",ans-1);//开始时间定为1
else
printf("KAKTUS");
return 0;
}
法二代码
#include<cstdio>
#include<queue>
#include<vector>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN=50,INF=0x3f3f3f3f;
char a[MAXN+5][MAXN+5];
int dir1[5]={-1,0,1,0},dir2[5]={0,1,0,-1};
int f[MAXN+5][MAXN+5];//洪水到达(i,j)的最早时间
int t[MAXN+5][MAXN+5];
int n,m,ans=0x3f3f3f3f;
int sx,sy,tx,ty;
bool flag=false;
struct node
{
int x,y;
};
vector<node> water;
void bfs1()
{
queue<node> que;
node q,tmp;
for(int i=0;i<water.size();i++)
{
f[water[i].x][water[i].y]=1;//开始时间定为1
que.push(water[i]);
}
while(!que.empty())
{
q=que.front();
que.pop();
for(int i=0;i<4;i++)
{
int dx=q.x+dir1[i],dy=q.y+dir2[i];
if(f[dx][dy]==INF&&(a[dx][dy]=='.'||a[dx][dy]=='S'))
{
f[dx][dy]=min(f[dx][dy],f[q.x][q.y]+1);
tmp.x=dx,tmp.y=dy;
que.push(tmp);
}
}
}
}
void bfs2()
{
queue<node> que;
t[sx][sy]=1;//开始时间定为1
node q,tmp;
q.x=sx,q.y=sy;
que.push(q);
while(!que.empty())
{
q=que.front();
que.pop();
for(int i=0;i<4;i++)
{
int dx=q.x+dir1[i],dy=q.y+dir2[i];
if(a[dx][dy]=='D')
{
flag=true;
ans=min(ans,t[q.x][q.y]+1);
}
if(a[dx][dy]=='.'&&t[q.x][q.y]+1<f[dx][dy]&&!t[dx][dy])
{
t[dx][dy]=t[q.x][q.y]+1;
tmp.x=dx,tmp.y=dy;
que.push(tmp);
}
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%s",a[i]+1);
for(int j=1;j<=m;j++)
{
if(a[i][j]=='S')
sx=i,sy=j;
if(a[i][j]=='D')
tx=i,ty=j;
if(a[i][j]=='*')//好像没说洪水起点只有一个...
{
node tmp;
tmp.x=i,tmp.y=j;
water.push_back(tmp);
}
}
}
memset(f,INF,sizeof(f));
if(water.size()>0)
bfs1();
bfs2();
if(flag)
printf("%d",ans-1);//开始时间定为1
else
printf("KAKTUS");
return 0;
}