题目来源:中山纪念中学
题目描述:
一天, 一个画家在森林里写生,突然爆发了山洪,他需要尽快返回住所中,那里是安
全的。
森林的地图由R行C列组成,空白区域用点“.”表示,洪水的区域用“*” 表示,而
岩石用“X”表示,另画家的住所用“D”表示,画家用“S”表示。
有以下几点需要说明:
1、 每一分钟画家能向四个方向移动一格(上、下、左、右)
2、 每一分钟洪水能蔓延到四个方向的相邻格子(空白区域)
3、 洪水和画家都不能通过岩石区域
4、 画家不能通过洪水区域(同时也不行,即画家不能移到某个格子,该格子在画家达到的同时被洪水蔓延到了,这也是不允许的)
5、 洪水蔓不到画家的住所。
给你森林的地图,编写程序输出最少需要花费多长时间才能从开始的位置赶回家中。
输入:
输入第一行包含两个整数R和C(R,C<=50)。
接下来R行每行包含C个字符(“.”、“*”、“X”、“D”或“S”)。地图保证只有一个“D”和一个“S”。
输出:
输出画家最快安全到达住所所需的时间,如果画家不可能安全回家则输出“KAKTUS”。
输入样例:
输入1:
3 3
D.*
…
.S.
输入2:
3 3
D.*
…
…S
输入3:
3 6
D…*.
.X.X…
…S.
输出样例:
输出1:
3
输出2:
KAKTUS
输出3:
6
思路:BFS
1、标记每个空地最早被洪水蔓延到的时间
2、从画家出发,然后跑一遍BFS,边界、障碍物、到达格子时间大于洪水淹没格子时间的格子不能走
AC代码:
#include<bits/stdc++.h>
using namespace std;
int r,c,vis[51][51],b[51][51],anss;
int dx[5]={0,-1,1,0,0};
int dy[5]={0,0,0,-1,1};
char a[51][51];
struct node{
int x;
int y;
int step;
}st,ed;
queue <node> q;
bool pd_flood(node d)
{
if (d.x<=r&&d.x>=1&&d.y<=c&&d.y>=1&&a[d.x][d.y]=='.'&&vis[d.x][d.y]==0) return true;
return false;
}
bool pd_art(node d)
{
if (d.x<=r&&d.x>=1&&d.y<=c&&d.y>=1&&a[d.x][d.y]=='.'&&vis[d.x][d.y]==0&&d.step<b[d.x][d.y]||a[d.x][d.y]=='D') return true;
return false;
}
void bfs_flood()//标记每个空地最早被洪水蔓延到的时间
{
while (!q.empty())
{
node flood=q.front();
q.pop();
vis[flood.x][flood.y]=1;//访问标记
b[flood.x][flood.y]=flood.step;
for (int i=1;i<=4;i++) //可以往四个方向蔓延
{
node fx;
fx.x=flood.x+dx[i];
fx.y=flood.y+dy[i];
fx.step=flood.step+1;
if (pd_flood(fx)==true) //洪水可以蔓延到这个点
{
vis[fx.x][fx.y]=1;
q.push(fx);
}
}
}
}
int bfs_art()
{
while (!q.empty())
{
node art=q.front();
q.pop();
if (art.x==ed.x&&art.y==ed.y) return art.step;//到家
vis[art.x][art.y]=1;//访问标记
for (int i=1;i<=4;i++) //可以往四个方向走
{
node fx;
fx.x=art.x+dx[i];
fx.y=art.y+dy[i];
fx.step=art.step+1;
if (pd_art(fx)==true) //画家可以走这个点
{
vis[fx.x][fx.y]=1;
q.push(fx);
}
}
}
return -1;//画家无家可归
}
int main()
{
scanf("%d%d",&r,&c);
for (int i=1;i<=r;i++)
{
scanf("%s",a[i]+1);
for (int j=1;j<=c;j++)
{
if (a[i][j]=='S') st.x=i,st.y=j,st.step=0;//起点
if (a[i][j]=='D') ed.x=i,ed.y=j;//终点
if (a[i][j]=='*') //洪水蔓延开始点
{
node flood;
flood.x=i;
flood.y=j;
flood.step=0;
q.push(flood);
}
}
}
memset(b,0x7f,sizeof(b));//初始化每个格子被洪水覆盖的时间为无限大,以免出现没有洪水的情况
bfs_flood();//洪水蔓延啦
while (!q.empty()) q.pop();
q.push(st);
memset(vis,0,sizeof(vis));
anss=bfs_art();//画家找家ing
if (anss==-1) cout<<"KAKTUS"<<endl;
else cout<<anss<<endl;
return 0;
}
虽然很长,可是思路清晰