POJ2251 Dungeon Master

题目链接

Dungeon Master

Description

You are trapped in a 3D dungeon and need to find the quickest way out! The dungeon is composed of unit cubes which may or may not be filled with rock. It takes one minute to move one unit north, south, east, west, up or down. You cannot move diagonally and the maze is surrounded by solid rock on all sides.
Is an escape possible? If yes, how long will it take?

Input

The input consists of a number of dungeons. Each dungeon description starts with a line containing three integers L, R and C (all limited to 30 in size).
L is the number of levels making up the dungeon.
R and C are the number of rows and columns making up the plan of each level.
Then there will follow L blocks of R lines each containing C characters. Each character describes one cell of the dungeon. A cell full of rock is indicated by a ‘#’ and empty cells are represented by a ‘.’. Your starting position is indicated by ‘S’ and the exit by the letter ‘E’. There’s a single blank line after each level. Input is terminated by three zeroes for L, R and C.

Output

Each maze generates one line of output. If it is possible to reach the exit, print a line of the form

Escaped in x minute(s).
where x is replaced by the shortest time it takes to escape.
If it is not possible to escape, print the line Trapped!

Sample Input(无语了,#连载一排没法显示,不做了,样例在链接里有)
Sample Output

Escaped in 11 minute(s).
Trapped!

BFS进一步训练,读题可以明白,
#代表没法走
.代表可以走
S代表起点
E代表终点
在一个三维的空间里规定了长宽高,找出最短从S到达E的步数

先来一波BFS三连:结构体、边界、初始化队列

1、结构体的定义

显然,结构体应该包括长宽高(理解成层数,行数,列数比较好)和到达该点的最短步数

typedef struct {
 int floor,x,y;//坐标,
 int time;//深度
}H;
H h1, h2;//搬运工和检查员
2、边界的规定

退出搜索的边界:
题意可知,当找到E所在的坐标的时候,停止搜索,准备进行返回
不合规操作的判定:
搜索出了输入的范围,比如跑到-1层啥的

3、队列的初始化

显然,在输入迷宫的同时需要找到E和S,这是两个不同的元素(特殊元素处理),需要把S的坐标存到全局变量(START)进行初始化

三连之后就应该研究操作了
很明显的,包括了上下左右前后(层数±1、行数±1、列数±1)因为我直接把S存到了全局变量中去,所以BFS根本就没带参数(果然带不带参数不是定死了的,是根据实际情况来的)

#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
typedef long long ll;
inline ll read() {//读入挂
 ll c = getchar(), Nig = 1, x = 0;
 while (!isdigit(c) && c != '-')c = getchar();
 if (c == '-')Nig = -1, c = getchar();
 while (isdigit(c))x = ((x << 1) + (x << 3)) + (c ^ '0'), c = getchar();
 return Nig * x;
}
inline void Out(ll a)
{//输出挂
 if (a < 0)putchar('-'), a = -a;
 if (a >= 10)Out(a / 10);//记得这是a>=10,让坑坏了
 putchar(a % 10 + '0');
}
typedef struct {
 int floor,x,y;//坐标
 int time;//深度
}H;
H h1, h2;//搬运工和检查员
H START, END;//全局边界
bool jud[37][37][37];//标记状态是否存在
char T[37][37][37];//开大一点,可以用0做边界,不用担心数组越界的问题
queue<H>Q;//队列
H step[7] = {{0,0,0,0},{1,0,0,1},{-1,0,0,1},{0,1,0,1},{0,-1,0,1},{0,0,1,1},{0,0,-1,1} };//六步操作,分别是上下层,上下行,左右列
int BFS() {//不用参数做边界
 h2.floor = START.floor;
 h2.x = START.x;
 h2.y = START.y;
 h2.time = 0;
 Q.push(h2);//用起点初始化队列
 while (!Q.empty()) {
  h1 = Q.front();
  Q.pop();
  if (h1.floor == END.floor && h1.x == END.x && h1.y == END.y) {//到达终点
   while (!Q.empty()) {
    Q.pop();//清空
   }
   return h1.time;//返回走的步数
  }

  //上一层
  h2.floor = h1.floor + step[1].floor;
  h2.x = h1.x + step[1].x;
  h2.y = h1.y + step[1].y;
  h2.time = h1.time + step[1].time;
  if (!jud[h2.floor][h2.x][h2.y]&& T[h2.floor][h2.x][h2.y]) {//jud没标记而且不越界
   Q.push(h2);
   jud[h2.floor][h2.x][h2.y] = true;
  }
  
  //下一层
  h2.floor = h1.floor + step[2].floor;
  h2.x = h1.x + step[2].x;
  h2.y = h1.y + step[2].y;
  h2.time = h1.time + step[2].time;
  if (!jud[h2.floor][h2.x][h2.y] && T[h2.floor][h2.x][h2.y]) {//jud没标记而且不越界
   Q.push(h2);
   jud[h2.floor][h2.x][h2.y] = true;
  }
  
  //上一行
  h2.floor = h1.floor + step[3].floor;
  h2.x = h1.x + step[3].x;
  h2.y = h1.y + step[3].y;
  h2.time = h1.time + step[3].time;
  if (!jud[h2.floor][h2.x][h2.y] && T[h2.floor][h2.x][h2.y]) {//jud没标记而且不越界
   Q.push(h2);
   jud[h2.floor][h2.x][h2.y] = true;
  }
  
  //下一行
  h2.floor = h1.floor + step[4].floor;
  h2.x = h1.x + step[4].x;
  h2.y = h1.y + step[4].y;
  h2.time = h1.time + step[4].time;
  if (!jud[h2.floor][h2.x][h2.y] && T[h2.floor][h2.x][h2.y]) {//jud没标记而且不越界
   Q.push(h2);
   jud[h2.floor][h2.x][h2.y] = true;
  }
  
  //右一列
  h2.floor = h1.floor + step[5].floor;
  h2.x = h1.x + step[5].x;
  h2.y = h1.y + step[5].y;
  h2.time = h1.time + step[5].time;
  if (!jud[h2.floor][h2.x][h2.y] && T[h2.floor][h2.x][h2.y]) {//jud没标记而且不越界
   Q.push(h2);
   jud[h2.floor][h2.x][h2.y] = true;
  }
  
  //左一列
  h2.floor = h1.floor + step[6].floor;
  h2.x = h1.x + step[6].x;
  h2.y = h1.y + step[6].y;
  h2.time = h1.time + step[6].time;
  if (!jud[h2.floor][h2.x][h2.y] && T[h2.floor][h2.x][h2.y]) {//jud没标记而且不越界
   Q.push(h2);
   jud[h2.floor][h2.x][h2.y] = true;
  }
 }
 return -1;
}
int main() {
 int floor, x,  y;
 while (floor = read() ,  x = read(),  y = read()) {
  if (floor == x && x == y && y == 0)
   break;
  char temp;
  for (int i = 1; i <= floor; i++) {//用1开始是为了用0做边界
   for (int j = 1; j <= x; j++) {
    for (int k = 1; k <= y; k++) {
     temp = getchar();
     if (temp == 'S') {//找到起点并数据标记到START
      START.floor = i;
      START.x = j;
      START.y = k;
     }
     if(temp == 'E') {//终点,数据标记到END
      END.floor = i;
      END.x = j;
      END.y = k;
     }
     if (temp == '#')
      jud[i][j][k] = true;//提前标记不可到达
     T[i][j][k] = temp;//存入数组
    }
    getchar();//每一列输入完毕都要吞掉回车,这一行要尤其注意,这题对getchar()的要求还挺高
   }
   getchar();//每一层输入完毕也要吞掉回车
  
  int Temp = BFS();
  if (Temp==-1) {
   cout << "Trapped!" << endl;
  }
  else {
   cout << "Escaped in " << Temp << " minute(s)." << endl;
  }
  memset(jud,0,sizeof(jud));//多组输入的必要操作
  memset(T,0,sizeof(T));//避免影响后续数据的判断
 }
}

补充一点:走迷宫类的操作可以把操作表示成数组,做起来更方便(运算符崇重载不太会啊啊啊啊,要不然写起来更方便)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值