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
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值