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!

简单的说就是在三维地图中找最短路,具体题目请参见POJ2251

一、普通的bfs,配合优先队列

代码如下:

 #include<stdio.h>
#include<iostream>
#include<queue>
using namespace std;
char map[][][]; //记录节点信息
int sta[][][]; //标记是否访问
int base[][] = { {-,,},{,,},{,-,},{,,},{,,-},{,,} };
int L, R, C;
struct Piont
{
int x, y, z; //位置坐标
int step; //出发点到该点的步数
};
struct Piont s; //起点
struct Piont e; //终点
struct Piont curp; //跳出循环时的节点 /******************判断是否到达终点*********************/
bool success(struct Piont cur)
{
if (cur.x == e.x && cur.y == e.y && cur.z == e.z)
return true;
else
return false;
} /**************判断该点是否合法*************************/
bool check(int x, int y, int z)
{
if ((x >= ) && (x < L) && (y >= ) && (y < R) && (z >= ) && (z < C) && (!sta[x][y][z]) && (map[x][y][z] == '.' || map[x][y][z] == 'E'))
return true;
else
return false;
} /*************************深搜***************************/
void bfs()
{
struct Piont next;
queue<Piont>q;
q.push(s);
//int flag = 0;
while (!q.empty())
{
curp = q.front();
q.pop();
if (success(curp))
return;
else
{
sta[curp.x][curp.y][curp.z] = ;
for (int i = ; i < ; i++)
{
next.x = curp.x + base[i][];
next.y = curp.y + base[i][];
next.z = curp.z + base[i][];
if (check(next.x, next.y, next.z)) //扩展队列
{
next.step = curp.step + ;
sta[next.x][next.y][next.z] = ;
q.push(next);
}
}
}
}
}
int main()
{
while (scanf("%d%d%d", &L, &R, &C))
{
if((L == ) && (R == ) && (C == ))
break;
memset(sta, , sizeof(sta));
for (int i = ; i < L; i++) {
getchar();
for (int j = ; j < R; j++) {
for (int k = ; k < C; k++)
{
scanf("%c", &map[i][j][k]);
if (map[i][j][k] == 'S') {
s.x = i;
s.y = j;
s.z = k;
s.step = ;
}
else if (map[i][j][k] == 'E')
{
e.x = i;
e.y = j;
e.z = k;
}
}
getchar();
}
}
bfs();
if (curp.x == e.x && curp.y == e.y && curp.z == e.z)
printf("Escaped in %d minute(s).\n", curp.step);
else
printf("Trapped!\n");
}
return ;
}

二、递归(但由于多次重复经过某点,时间复杂度远大于方法一)

仅供参考,代码如下:

 #include<stdio.h>
#include<iostream>
using namespace std;
char map[][][];
int step_map[][][];
int sta[][][];
int s_x = -, s_y = -, s_z = -;
int e_x = -, e_y = -, e_z = -;
int step = , minn = << ;
int L, R, C;
int base[][] = { {-,,},{,,},{,-,},{,,},{,,-},{,,} }; bool check(int x, int y, int z)
{
if ((x >= ) && (x < L) && (y >= ) && (y < R) && (z >= ) && (z < C))
return true;
else
return false;
}
void bfs(int x, int y, int z)
{
int temp_x, temp_y, temp_z;
for (int i = ; i < ; i++)
{
if (x == e_x + base[i][] && y == e_y + base[i][] && z == e_z + base[i][])
{
if (step < minn)
minn = step;
return;
}
}
for (int i = ; i < ; i++)
{
temp_x = x + base[i][];
temp_y = y + base[i][];
temp_z = z + base[i][];
if ((!sta[temp_x][temp_y][temp_z]) && (map[temp_x][temp_y][temp_z] == '.') && (check(temp_x, temp_y, temp_z)))
{
step++;
if (step < step_map[temp_x][temp_y][temp_z]) //剪枝二:当前步数已大于曾经过该点的最小步数,停止搜索
{
step_map[temp_x][temp_y][temp_z] = step;
if (step < minn) //剪枝一:当前步数已大于或等于最小步数,停止搜索
{
sta[temp_x][temp_y][temp_z] = ;
bfs(temp_x, temp_y, temp_z);
sta[temp_x][temp_y][temp_z] = ;
}
}
step--;
}
}
}
int main()
{
while (scanf("%d%d%d",&L,&R,&C))
{
if ((L == ) && (R == ) && (C == ))
break;
memset(sta, , sizeof(sta));
//memset(step_map, (1 << 25), sizeof(step_map));//只能用来初始化为0、1和-1
for (int i = ; i < ; i++)
for (int j = ; j < ; j++)
for (int k = ; k < ; k++)
step_map[i][j][k] = ( << ); for (int i = ; i < L; i++) {
getchar();
for (int j = ; j < R; j++) {
for (int k = ; k < C; k++)
{
//cin >> map[i][j][k];
scanf("%c", &map[i][j][k]);
if (map[i][j][k] == 'S') {
s_x = i;
s_y = j;
s_z = k;
}
if (map[i][j][k] == 'E')
{
e_x = i;
e_y = j;
e_z = k;
}
}
getchar();
}
} bfs(s_x, s_y, s_z);
if (minn == ( << ))
printf("Trapped!");
else
{
printf("Escaped in %d minnute(s).", minn + );
minn = ( << );
step = ;
}
}
return ;
}

新手入门,希望大家多多指教!

Dungeon Master的两种方法的更多相关文章

  1. hive权威安装出现的不解错误!(完美解决)两种方法都可以

    以下两种方法都可以,推荐用方法一! 方法一: 步骤一: yum -y install mysql-server 步骤二:service mysqld start 步骤三:mysql -u root - ...

  2. 两种方法上传本地文件到github

    https://www.jianshu.com/p/c70ca3a02087 自从使用github以来,一直都是在github网站在线上传文件到仓库中,但是有时因为网络或者电脑的原因上传失败.最重要的 ...

  3. 两种方法上传本地文件到github(转)

    自从使用github以来,一直都是在github网站在线上传文件到仓库中,但是有时因为网络或者电脑的原因上传失败.最重要的原因是我习惯本地编辑,完成以后再一起上传github.看过了几个教程,总结出最 ...

  4. 在vc6.0下编的对话框界面如果没做过其他处理,往往显的很生硬,怎么样才能使他有Windows XP的风格呢,其实也很简单,我们来看看下面两种方法。

    在vc6.0下编的对话框界面如果没做过其他处理,往往显的很生硬,怎么样才能使他有Windows XP的风格呢,其实也很简单,我们来看看下面两种方法.    方法一: 1.首先确认你在Windows   ...

  5. [整理] C#调用SQLDMO.DLL时间数据库备份 / 还原。 (香神无涯) // C#实现SQLSERVER2000数据库备份还原的两种方法 (带进度条)

    /// <summary>/// 通过调用MSSQL的SQLDMO.DLL文件来实现备份数据库/// 1.首先在在项目中引用SQLDMO.DLL文件./// 2.在引用中的SQLDMO.D ...

  6. GitHub常用上传文件的两种方法 附带常见的问题及Git安装教程

    从早上下课到现在一直在琢磨如何给Github下载本地文件,中午饭都没吃.还好是解决了,感觉挺有成就感的.O(∩_∩)O哈哈~ 好哒 闲话不说,说重点. 一.git的安装 百度云:http://pan. ...

  7. Git恢复之前版本的两种方法reset、revert

    实战 回退 1.删除之前的提交 git reset --hard id 推送到远程 git push -f [git log中确实删除了,但是拿到可以恢复] 2.不删除之前的提交 git revert ...

  8. windows下获取IP地址的两种方法

    windows下获取IP地址的两种方法: 一种可以获取IPv4和IPv6,但是需要WSAStartup: 一种只能取到IPv4,但是不需要WSAStartup: 如下: 方法一:(可以获取IPv4和I ...

  9. android 之 启动画面的两种方法

    现在,当我们打开任意的一个app时,其中的大部分都会显示一个启动界面,展示本公司的logo和当前的版本,有的则直接把广告放到了上面.启动画面的可以分为两种设置方式:一种是两个Activity实现,和一 ...

随机推荐

  1. 分享微信h5支付经验

    <?php //use Flight; /** * 微信支付服务器端下单 * 微信APP支付文档地址: https://pay.weixin.qq.com/wiki/doc/api/app.ph ...

  2. 2014-10-22 NOIP模拟赛

    1 1 .传教士 (bishop) 问题描述:panzhili 王国的疆土恰好是一个矩形,为了管理方便,国王 jjs 将整个疆土划分成 N*M 块大小相同的区域.由于 jjs 希望他的子民也能信教爱教 ...

  3. Manacher(hdu3068最长回文)

    浅谈manacher算法 manacher算法是我在网上无意中找到的,主要是用来求某个字符串的最长回文子串. 不过网上的版本还不太成熟,我就修改了下. 不要被manacher这个名字吓倒了,其实man ...

  4. 关于c语言中的字符串问题

    对字符数组,字符指针,字符串常量 在csdn上看到一篇关于这方面的帖子,有所收获. JohnTitor的专栏 1.以字符串形式出现的,编译器都会为该字符串自动添加一个0作为结束符,如在代码中写   & ...

  5. [Xcode 实际操作]七、文件与数据-(3)创建文本文件、属性列表文件、图片文件

    目录:[Swift]Xcode实际操作 本文将演示如何创建各种类型的文件. 在项目导航区,打开视图控制器的代码文件[ViewController.swift] import UIKit class V ...

  6. [Xcode 实际操作]六、媒体与动画-(12)检测UIView动画的结束事件:反转动画并缩小至不可见状态

    目录:[Swift]Xcode实际操作 本文将演示UIView视图反转动画的制作,并检测其动画结束事件. 即视图在进行反转动画的同时,将移动到目标位置,并缩小至不可见状态. 在项目导航区,打开视图控制 ...

  7. MyBatis日志实现

    maven项目resources文件夹下log4j.properties 其作用是输出controller包下参与Mybatis的类的SQL语句输出.如果包名不一样,请根据自己的项目情况调整. # G ...

  8. 线程组之间的JMeter传递变量

    在这个JMeter教程中,我们将了解如何在线程组之间共享和传递变量. 在开发高级JMeter脚本时,很可能您将拥有多个线程组.每个线程组将执行不同的请求. 一个很好的例子就是我们需要使用Bearer ...

  9. C8051开发环境

    1 keilC51 2 Silicon Laboratories C8051Fxxx uVision Driver_4 C:\Keil9 3  Silicon Laboratories Configu ...

  10. GPIO的翻转操作方法

    STM32在进行IO翻转操作的时候可以使用以下方法:以PE.5为例 GPIO_WriteBit(GPIOE,GPIO_Pin_5,(BitAction)(1-(GPIO_ReadOutputDataB ...