【BFS】洪水

描述

  魔法森林的地图是R行C列的矩形。能通行的空地表示为‘.‘,C君倾倒洪水的地点标记为‘*‘,无法通行的巨石阵标记为‘X‘,海狸的巢穴标记为‘D‘,而画家和三只小刺猬的初始位置标记为‘S‘。

  每一分钟,画家和三个小刺猬可以走到相邻(上、下、左或右)的四个空地之一。与此同时,洪水每一分钟也会扩大到相邻(上、下、左或右)的所有的空地。一旦空地被淹没,就无法再通行。洪水无法通过巨石阵。但是海狸的巢穴建在很高的地方,永远不会淹没。

  注意,画家和三只小刺猬无法进入即将被淹没的空地,即如果他们与洪水在同一分钟到达某个空地,就不能进入。

题目

  编写一个程序,给定一个魔法森林的地图,输出为了让画家和三只小刺猬安全地到达海狸的巢穴所需的最短时间。

输入

  第1行:2个整数R,C

  接下来R行,每行C个字符 (‘.‘, ‘*‘, ‘X‘, ‘D‘ 或 ‘S‘)

  地图只含有恰好1个‘D‘和1个‘S‘,而‘*‘可能有零个或多个

输出

  1个整数,表示最短的到达狸的巢穴所需的时间。如果无法到达,输出"KAKTUS"。并且我当初刚学,还小用的两个参数的增加比较来代替队列

输入样例1

3 6
D...*.
.X.X..
....S.

  

输出样例1

6

  

输入样例2

3 3
D.*
...
..S

  

输出样例2

KAKTUS

  

输入样例3

3 3
D.*
...
.S.

  

输出样例3

3

  

解题思路

  以洪水和人为起点分别搜索,记录深度,再作出比较,输出答案。

题解

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 int b[51][51];//存图
  4 bool w[51][51];//是否被水蔓延
  5 int water[2501][2];//水的横纵坐标
  6 int state[2501][2];
  7 int dep[51][51][2];//0为水的深度,1为人的深度
  8 int sx,sy,ex,ey,n,m,k;
  9 int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};
 10 bool in(int x,int y)//判断界限
 11 {
 12     return x>=1&&x<=n&&y>=1&&y<=m&&b[x][y]==0;
 13 }
 14 bool in_(int x,int y,int z)//判断界限并与洪水深度作比较
 15 {
 16     return x>=1&&x<=n&&y>=1&&y<=m&&b[x][y]<=0&&z<dep[x][y][0];
 17 }
 18 void bfs1()//洪水搜索
 19 {
 20     int h=0;
 21     memset(w,0,sizeof(w));//清空标记
 22     do
 23     {
 24         h++;//当前洪水编号 (扩展结点)
 25         for(int i=0;i<=3;i++)//四方向延伸
 26             if(in(water[h][0]+dx[i],water[h][1]+dy[i])&&!w[water[h][0]+dx[i]][water[h][1]+dy[i]])//是否合法
 27             {
 28                 k++;//总洪水编号 (子结点)
 29                 water[k][0]=water[h][0]+dx[i];
 30                 water[k][1]=water[h][1]+dy[i];//记录横纵坐标
 31                 w[water[k][0]][water[k][1]]=1;//打标记
 32                 dep[water[k][0]][water[k][1]][0]=dep[water[h][0]][water[h][1]][0]+1;//记录深度
 33             }
 34     }
 35     while (h<k);//控制水的蔓延
 36 }
 37 void bfs2()//人的搜索
 38 {
 39     int h=0,t=1;
 40     memset(w,0,sizeof(w));//清空标记
 41     state[1][0]=sx;state[1][1]=sy;w[sx][sy]=1;
 42     do
 43     {
 44         h++;//现在人编号
 45         for(int i=0;i<=3;i++)
 46             if (in_(state[h][0]+dx[i],state[h][1]+dy[i],dep[state[h][0]][state[h][1]][1]+1)&&!w[state[h][0]+dx[i]][state[h][1]+dy[i]])
 47             {
 48                 t++;//总数编号
 49                 state[t][0]=state[h][0]+dx[i];
 50                 state[t][1]=state[h][1]+dy[i];//记录横纵坐标
 51                 w[state[t][0]][state[t][1]]=1;//打标记
 52                 dep[state[t][0]][state[t][1]][1]=dep[state[h][0]][state[h][1]][1]+1;//记录深度
 53             }
 54     }
 55     while (h<t);//控制人的蔓延
 56 }
 57 int main()
 58 {
 59     char p;
 60     scanf("%d%d",&n,&m);
 61     for(int i=1;i<=n;i++)
 62     {
 63         for(int j=1;j<=m;j++)
 64         {
 65             dep[i][j][0]=2147483647;//初始化洪水深度
 66         }
 67     }
 68     for(int i=1;i<=n;i++)
 69     {
 70         for(int j=1;j<=m;j++)
 71         {
 72                 cin>>p;
 73                 switch(p)
 74                 {
 75                     case ‘S‘://起点
 76                     {
 77                         sx=i;sy=j;
 78                         break;
 79                     }
 80                     case ‘X‘://障碍物
 81                     {
 82                         b[i][j]=1;
 83                         break;
 84                     }
 85                     case ‘*‘://洪水点
 86                     {
 87                         k++;
 88                         water[k][0]=i;water[k][1]=j;
 89                         dep[i][j][0]=0;
 90                         b[i][j]=2;
 91                         break;
 92                     }
 93                     case ‘D‘://终点
 94                     {
 95                         ex=i;ey=j;
 96                         b[i][j]=-1;
 97                         break;
 98                     }
 99                     default:
100                     {
101                         break;
102                     }
103                 }
104         }
105     }
106     if(k!=0)bfs1();//有洪水就搜索
107     bfs2();//人的搜索
108     if(dep[ex][ey][1]!=0)printf("%d",dep[ex][ey][1]);//搜到了终点就输出
109     else printf("KAKTUS");//否则输出 KAKTUS
110 }

原文地址:https://www.cnblogs.com/hualian/p/11153032.html

时间: 2024-08-03 09:07:07

【BFS】洪水的相关文章

[noip模拟]水灾&lt;BFS&gt;

水灾(sliker.cpp/c/pas) 1000MS  64MB 大雨应经下了几天雨,却还是没有停的样子.土豪CCY刚从外地赚完1e元回来,知道不久除了自己别墅,其他的地方都将会被洪水淹没. CCY所在的城市可以用一个N*M(N,M<=50)的地图表示,地图上有五种符号:“. * X D S”.其中“X”表示石头,水和人都不能从上面经过.“.”表示平原,CCY和洪水都可以经过.“*”表示洪水开始地方(可能有多个地方开始发生洪水).“D”表示CCY的别墅.“S”表示CCY现在的位置. CCY每分

[POI2007]洪水pow 题解

[POI2007]洪水pow 时间限制: 5 Sec  内存限制: 128 MB 题目描述 AKD市处在一个四面环山的谷地里.最近一场大暴雨引发了洪水,AKD市全被水淹没了.Blue Mary,AKD市的市长,召集了他的所有顾问(包括你)参加一个紧急会议.经过细致的商议之后,会议决定,调集若干巨型抽水机,将它们放在某些被水淹的区域,而后抽干洪水.你手头有一张AKD市的地图.这张地图是边长为m*n的矩形,被划分为m*n个1*1的小正方形.对于每个小正方形,地图上已经标注了它的海拔高度以及它是否是A

codevs3411 洪水

题目描述 Description 小浣熊松松和朋友到野外露营,没想到遇上了π年一次的大洪水,好在松松是一只爱观察的小浣熊,他发现露营地的地形和洪水有如下性质: ①露营地可以被看做是一个N*M的矩形方阵,其中左上角坐标为(1,1),右下角坐标为(n,m),每个格子(i,j)都有一个高度h(i,j). ②洪水送(r,c)开始,如果一个格子被洪水淹没,那这个格子四周比它低(或相同)的格子也会被淹没. 现在松松想请你帮忙算算,有多少个格子不会被淹没,便于他和朋友逃脱. [原有误数据已删除] 输入描述 I

[POI2007]洪水pow

问题 E: [POI2007]洪水pow 时间限制: 5 Sec  内存限制: 128 MB 题目描述 AKD市处在一个四面环山的谷地里.最近一场大暴雨引发了洪水,AKD市全被水淹没了.Blue Mary,AKD市的市长,召集了他的所有顾问(包括你)参加一个紧急会议.经过细致的商议之后,会议决定,调集若干巨型抽水机,将它们放在某些被水淹的区域,而后抽干洪水.你手头有一张AKD市的地图.这张地图是边长为m*n的矩形,被划分为m*n个1*1的小正方形.对于每个小正方形,地图上已经标注了它的海拔高度以

CODE[VS] 3411 洪水

题目描述 Description 小浣熊松松和朋友到野外露营,没想到遇上了π年一次的大洪水,好在松松是一只爱观察的小浣熊,他发现露营地的地形和洪水有如下性质: ①露营地可以被看做是一个N*M的矩形方阵,其中左上角坐标为(1,1),右下角坐标为(n,m),每个格子(i,j)都有一个高度h(i,j). ②洪水送(r,c)开始,如果一个格子被洪水淹没,那这个格子四周比它低(或相同)的格子也会被淹没. 现在松松想请你帮忙算算,有多少个格子不会被淹没,便于他和朋友逃脱. [原有误数据已删除] 输入描述 I

题解1235. 洪水 (Standard IO)

Description 一天, 一个画家在森林里写生,突然爆发了山洪,他需要尽快返回住所中,那里是安全的.森林的地图由R行C列组成,空白区域用点“.”表示,洪水的区域用“*”表示,而岩石用“X”表示,另画家的住所用“D”表示,画家用“S”表示.有以下几点需要说明:1. 每一分钟画家能向四个方向移动一格(上.下.左.右)2. 每一分钟洪水能蔓延到四个方向的相邻格子(空白区域)3. 洪水和画家都不能通过岩石区域4. 画家不能通过洪水区域(同时也不行,即画家不能移到某个格子,该格子在画家达到的同时被洪

[noip] bfs算法整理

BFS : 1.普通队列:维护 (1)两段性(队列中至多有x和x+1两种距离) (2)单调性 首次入队即为最短距离(所以通常要判重) 2.优先队列: 可能入队出队多次,通常首次 出 队即为最短距离(无需判重) 一.模型 1.flood fill(洪水填充,即连通块模型) 2.最短路(通常在网格图上,线性状态数量) 1)边权都为1 2)边权为0或1(使用双端队列,边权为0的放入队首,边权为1的放入队尾) 3.最小步数模型(把某状态操作前和操作后连一条边,边权为1) 二.优化(状态数量很多,状态扩展

[hdu 2102]bfs+注意INF

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2102 感觉这个题非常水,结果一直WA,最后发现居然是0x3f3f3f3f不够大导致的--把INF改成INF+INF就过了. #include<bits/stdc++.h> using namespace std; bool vis[2][15][15]; char s[2][15][15]; const int INF=0x3f3f3f3f; const int fx[]={0,0,1,-1};

BFS+康托展开(洛谷1379 八数码难题)

在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变. 输入格式: 输入初试状态,一行九个数字,空格用0表示 输出格式: 只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数(测试数据中无特殊无法到达目标状态数据) 输入样例#1: 2831