信息学奥赛一本通 1248:Dungeon Master | OpenJudge NOI 2.5 1253:Dungeon Master

本文介绍了如何解决一个三维迷宫逃脱问题,使用广度优先搜索(BFS)算法寻找从起点到终点的最短路径。题目涉及多组数据,需要处理不同尺寸的地牢,并且明确了移动方向和边界条件。解题关键在于正确设置三维数组、节点坐标和方向数组,并在搜索过程中处理好边界和已访问节点的状态。最终通过实例展示了解法的正确性和效率。
摘要由CSDN通过智能技术生成

【题目链接】

ybt 1248:Dungeon Master
OpenJudge NOI 2.5 1253:Dungeon Master

【题目翻译】

地牢城主

描述

你被困在一个3D地牢中,需要找到可以走出地牢的最快的一条路。地牢由方块单位组成,方块中可能有或没有填满岩石。向东、南、西、北、上或下移动一个单位需要花费1分钟。你不可以向对角线方向移动。整个迷宫外各个方向都被坚硬的岩石包围。
是否可能逃脱呢?如果可能,需要用多久?

输入

输入包括一个地牢数字。每个地牢以包括L,R与C(大小都小于等于30)三个整数的一行开始。
L是地牢的层数。
R与C是每层平面的行数和列数。
接下来是L块,每块有R行,每行C个字符。每个字符表示一个地牢的房间。一个装满岩石的房间由’#‘表示,空房间由’.‘表示。你的起始位置由’S’表示,出口是字母’E’。每一层后有一个空行。
输入以表示L、R与C的三个0为结尾。

输出

每个迷宫产生一行输出。如果可能到达出口,如下面的格式输出一行:
Escaped in x minute(s).
x由逃离地牢所花费的最短时间代替
如果不可能逃离地牢,输出一行:
Trapped!

样例输入

3 4 5
S…
.###.
.##…
###.#

##.##
##…

#.###
####E

1 3 3
S##
#E#

0 0 0

样例输出

Escaped in 11 minute(s).
Trapped!

来源

Ulm Local 1997

【题目考点】

1. 搜索 迷宫问题

【解题思路】

二维迷宫问题可以参考:1251:仙岛求药
该题为三维迷宫问题,解题方法与二维迷宫问题类似,只需要将设的地图数组、vis数组变为三维、结点中表示坐标的变量设为三个。起点、终点坐标都是三维的,移动方向变为东西南北上下6个方向。
注意:

  • 多组数据问题,要做数据清空。
  • 输入数据时,先按层遍历,而后按行、按列遍历。要清楚三维数组第1、2、3维分别对应什么。

【题解代码】

解法1:广搜
#include<bits/stdc++.h>
using namespace std;
#define N 35
char mp[N][N][N];//地图 (x,y,z):x行y列z层 
int l, r, c, ans;//l:层数 r:行数 c:列数  
int sx, sy, sz, ex, ey, ez;//(sx,sy,sz):起点位置  (ex,ey,ez):终点位置 
int dir[6][3] = {{0,0,1},{0,0,-1},{0,1,0},{0,-1,0},{1,0,0},{-1,0,0}};//方向数组
bool vis[N][N][N];//vis[i][j][k]:(i,j,k)位置是否已经访问过 
struct Node
{
    int x, y, z, t;//走到位置:(x,y,z),时间t 
    Node(){}
    Node(int a, int b, int c, int d):x(a),y(b),z(c),t(d){}
};
int bfs()//从(sx,sy,sz)出发进行广搜,如果能到达终点(ex,ey,ez),返回时间。否则返回-1 
{
    queue<Node> que;
    vis[sx][sy][sz] = true;
    que.push(Node(sx, sy, sz, 0));
    while(que.empty() == false)
    {
        Node u = que.front();
        que.pop();
        if(u.x == ex && u.y == ey && u.z == ez)
            return u.t;
        for(int i = 0; i < 6; ++i)
        {
            int x = u.x + dir[i][0], y = u.y + dir[i][1], z = u.z + dir[i][2];
            if(x >= 1 && x <= r && y >= 1 && y <= c && z >= 1 && z <= l && vis[x][y][z] == false && mp[x][y][z] != '#')
            {
                vis[x][y][z] = true;
                que.push(Node(x, y, z, u.t+1));
            }
        }
    }
    return -1;
}
int main()
{
    while(cin >> l >> r >> c)
    {
        if(l == 0 && r == 0 && c == 0)
            break;
        for(int z = 1; z <= l; ++z)//层 
            for(int x = 1; x <= r; ++x)//行 
                for(int y = 1; y <= c; ++y)//列 
                {
                    cin >> mp[x][y][z];
                    if(mp[x][y][z] == 'S')
                        sx = x, sy = y, sz = z;
                    else if(mp[x][y][z] == 'E')
                        ex = x, ey = y, ez = z;
                }
        memset(vis, 0, sizeof(vis));
        ans = bfs();//求到达终点的时间     
        if(ans == -1)
            cout << "Trapped!" << endl;
        else
            cout << "Escaped in " << ans <<" minute(s)." << endl;
    }
    return 0;
}
Dungeon Master》通常是一个角色扮演游戏的概念,特别是在桌面游戏如龙与地下城(Dungeons & Dragons)中,DM(Dungeon Master)代表了游戏主持人或 Dungeon Master,负责创造、引导和管理游戏世界。在C++中,要实现这样一个游戏的一个简化版本,涉及到图形用户界面设计、游戏逻辑和规则处理等复杂部分。下面是一个非常基础的命令行版的角色扮演战斗模拟示例,不是完整的Dungeon Master游戏,但它展示了如何创建简单的角色和回合制战斗: ```cpp #include <iostream> #include <string> class Character { public: int health; int attack; Character(int h, int a): health(h), attack(a) {} void attack(Character& enemy) { if (health > 0 && enemy.health > 0) { int damage = attack - enemy.defense; std::cout << "You dealt " << damage << " damage to the enemy.\n"; enemy.health -= damage; if (enemy.health <= 0) std::cout << "Enemy defeated!\n"; } } private: int defense; // 假设每个角色有自己的防御值 }; int main() { Character player(100, 20); // 创建玩家,假设健康为100,攻击为20 Character enemy(50, 10); // 创建敌人,假设健康为50,攻击为10 while (player.health > 0 && enemy.health > 0) { player.attack(enemy); if (player.health <= 0) break; enemy.attack(player); // 敌人反击 } return 0; } ``` 这只是一个非常简化的例子,真正的《Dungeon Master》游戏将包括更复杂的地图探索、事件管理、角色技能系统、道具系统等。如果你想在C++中构建这样的完整游戏,你可能会需要学习并利用一些游戏开发库,例如SFML、Unity C#脚本或是Unreal Engine。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值