YCOJ【洪水】

描述

  魔法森林的地图是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