一本通题解——1251:仙岛求药
题目相关
题目链接
一本通 OJ,http://ybt.ssoier.cn:8088/problem_show.php?pid=1251。
计蒜客 OJ,https://nanti.jisuanke.com/t/T1212。
题目描述
少年李逍遥的婶婶病了,王小虎介绍他去一趟仙灵岛,向仙女姐姐要仙丹救婶婶。叛逆但孝顺的李逍遥闯进了仙灵岛,克服了千险万难来到岛的中心,发现仙药摆在了迷阵的深处。迷阵由M×N个方格组成,有的方格内有可以瞬秒李逍遥的怪物,而有的方格内则是安全。现在李逍遥想尽快找到仙药,显然他应避开有怪物的方格,并经过最少的方格,而且那里会有神秘人物等待着他。现在要求你来帮助他实现这个目标。下图,显示了一个迷阵的样例及李逍遥找到仙药的路线。
输入格式
输入有多组测试数据. 每组测试数据以两个非零整数 M 和 N 开始,两者均不大于20。M 表示迷阵行数, N 表示迷阵列数。接下来有 M 行, 每行包含N个字符,不同字符分别代表不同含义:
1)‘@’:少年李逍遥所在的位置;
2)‘.’:可以安全通行的方格;
3)‘#’:有怪物的方格;
4)‘*’:仙药所在位置。
当在一行中读入的是两个零时,表示输入结束。
输出格式
对于每组测试数据,分别输出一行,该行包含李逍遥找到仙药需要穿过的最少的方格数目(计数包括初始位置的方块)。如果他不可能找到仙药, 则输出 -1。
样例输入
8 8
.@##...#
#....#.#
#.#.##..
..#.###.
#.#...#.
..###.#.
...#.*..
.#...###
样例输出
10
题目分析
走迷宫问题,自然是典型的 BFS 模板题。
题意分析
一个 M*N 大小的迷宫,我们从 @ 位置出发(也就是起点),字符 . 表示可以安全通行的方格,字符 # 表示有怪物(也就是不能走),字符 * 表示仙药(也就是终点)。要求输出从 @ 到 * 的最短路径。那么迷宫问题的基本要素全齐了,所以本题就是一道 BFS 模板题。
样例数据分析
迷宫大小
w = 8,h=8。
坐标系建立
如下图所示,我们这样建立坐标系。
我比较喜欢从 0 开始,当然也可以从 1 开始建立。
起点坐标
从上图坐标系中,我们可以知道,起点 @ 的坐标为 (1, 0)。
终点坐标
从上图坐标系中,我们可以知道,终点 * 的坐标为 (5, 6)。
移动方式
一般走迷宫问题,缺省的移动方向就是四个,即上下左右。根据上面的坐标系,我们可以定义出如下的移动增量:
const POS move[] = {{-1,0}, {0,1}, {1,0}, {0,-1}};
从哪个方向开始,如何摆放位置,是不会影响最终的结果。
最终的移动路线
如下图绿色所示,最终最短的路径是 10 步。
算法思路
1、读入数据,并写入到合适的数据结构中。
2、找到起点位置,将起点加入到队列 q 中。
3、记录终点位置信息。
4、开始 BFS 遍历。直到找到终点或者遍历所有节点而无法到达终点。
AC 参考代码
#include <cstdio>
#include <queue>struct POS {int x, y;//当前结点坐标int cost;//从起点到当前结点的距离
};const int MAXN = 200;
struct MAZE {int m, n;//迷宫大小char data[MAXN][MAXN];//迷宫的数据bool visit[MAXN][MAXN];//是否已经走过int x1, y1;//起点信息int x2, y2;//终点信息
};int bfs(MAZE &maze);int main() {MAZE maze = {};scanf("%d %d", &maze.m, &maze.n);//读入迷宫int i, j;for (i=0; i<maze.m; i++) {for (j=0; j<maze.n; j++) {scanf(" %c", &maze.data[i][j]);if (maze.data[i][j]=='@') {//起点位置maze.x1 = i;maze.y1 = j;} else if (maze.data[i][j]=='*') {//终点位置maze.x2 = i;maze.y2 = j;}}}//使用 BFS 进行遍历printf("%d\n", bfs(maze));return 0;
}int bfs(MAZE &maze) {std::queue<POS> q;const POS move[] = {{-1,0}, {0,1}, {1,0}, {0,-1}};//定义移动方法POS cur, next;//加入起点,从起点位置开始遍历cur.x = maze.x1;cur.y = maze.y1;cur.cost = 0;maze.visit[cur.x][cur.y] = true;q.push(cur); //开始遍历while (!q.empty()) {//弹出队首节点cur = q.front();q.pop();//从队首节点出发,尝试所有的移动可能for (int i=0; i<4; i++) {//计算下一个节点坐标next.x = cur.x + move[i].x;next.y = cur.y + move[i].y;//判断是不是终点if (next.x==maze.x2 && next.y==maze.y2) {return cur.cost + 1;} //判断通过性if (next.x>=0&&next.x<maze.m&&next.y>=0&&next.y<maze.n&&maze.visit[next.x][next.y]==false&&maze.data[next.x][next.y]!='#') {//说明这个节点可以通过,加入到队列中next.cost = cur.cost + 1;if (maze.data[next.x][next.y]=='x') {next.cost++;}maze.visit[next.x][next.y] = true;q.push(next);}}}return -1;
}
代码分析
1、如何表示一个节点的坐标,以及该节点到起点的距离。这里我用一个自定义的结构体来表示。如下所示:
struct POS {int x, y;//当前结点坐标int cost;//从起点到当前结点的距离
};
2、如何表示一个迷宫。这里我将所有迷宫信息全部放在一个自定义结构体中,增强了代码可读性。如下所示:
const int MAXN = 200;
struct MAZE {int m, n;//迷宫大小char data[MAXN][MAXN];//迷宫的数据bool visit[MAXN][MAXN];//是否已经走过int x1, y1;//起点信息int x2, y2;//终点信息
};
3、如何表示所有移动可能性。如下所示:
const POS move[] = {{-1,0}, {0,1}, {1,0}, {0,-1}};//定义移动方法
4、新节点通过性判断问题。根据题目进行判断,基本包括以下几个方面:
(1)这个位置可以走,如本题中用字符 . 表示。如下所示:
maze.data[next.x][next.y]!='#'
(2)这个位置没有访问过。如下所示:
maze.visit[next.x][next.y]==false
(3)这个位置处于迷宫内。这个判断和您程序对迷宫定义有关。如下所示:
next.x>=0&&next.x<maze.m&&next.y>=0&&next.y<maze.n
P.S.
本题解不能完全适用于一本通的题目,因为一本通的输入里有多个迷宫。只需要将代码简单改动即可。
一本通题解——1251:仙岛求药相关推荐
- Java实现 计蒜客 1251 仙岛求药
仙岛求药 少年李逍遥的婶婶病了,王小虎介绍他去一趟仙灵岛,向仙女姐姐要仙丹救婶婶.叛逆但孝顺的李逍遥闯进了仙灵岛,克服了千险万难来到岛的中心,发现仙药摆在了迷阵的深处.迷阵由 M \times NM× ...
- 信息学奥赛一本通(1251:仙岛求药)
1251:仙岛求药 时间限制: 1000 ms 内存限制: 65536 KB 提交数: 11479 通过数: 4968 [题目描述] 少年李逍遥的婶婶病了,王小虎介绍他去一趟仙 ...
- 百练/ 北京大学2016研究生推免上机考试(校内)D: 仙岛求药(广度优先搜索)
题目来源:http://noi.openjudge.cn/ch0205/2727/ 2727:仙岛求药 总时间限制: 1000ms 内存限制:65536kB 描述 少年李逍遥的婶婶病了,王小虎介绍他 ...
- 仙岛求药(信息学奥赛一本通-T1251)
[题目描述] 少年李逍遥的婶婶病了,王小虎介绍他去一趟仙灵岛,向仙女姐姐要仙丹救婶婶.叛逆但孝顺的李逍遥闯进了仙灵岛,克服了千险万难来到岛的中心,发现仙药摆在了迷阵的深处.迷阵由M×N个方格组成,有的 ...
- 信息学奥赛一本通 题解目录
刷题 很全的知识体系 转载:https://blog.csdn.net/u011815404/article/details/79324003 第一部分 C++语言 第一章 C++语言入门 T1001 ...
- 信息学奥赛一本通(题解目录)
信息学奥赛一本通(题解目录) 记录了我从初学者到逐渐熟悉c++的成长之路 信息学奥赛一本通OJ 目录 信息学奥赛一本通(题解目录) 前言 一.语言及算法基础篇 基础(一) C++语言 第一章 C++语 ...
- 一本通题解——1438:灯泡
题目链接 一本通OJ:http://ybt.ssoier.cn:8088/problem_show.php?pid=1438. 我的OJ:http://47.110.135.197/problem.p ...
- 一本通题解——1433 愤怒的牛
题目链接 一本通:http://ybt.ssoier.cn:8088/problem_show.php?pid=1433. 自己OJ:http://47.110.135.197/problem.php ...
- PAT甲级1111 Online Map (30分):[C++题解]两次dijkstra求单源最短路、保存路径、长度最短、时间最短
文章目录 题目分析 题目链接 题目分析 来源:acwing 分析:dijkstra求单源最短路的题目. 只是写两遍而已,第一遍求按照路径长度求,第二遍按照时间最少求. 另外加一个vector路径的判断 ...
最新文章
- eclipse中报错:java.lang.OutOfMemoryError: Java heap space
- 得力助手 消防员的 消防机器人_消防机器人:消防员的“得力助手”
- keepalived配置高可用集群
- CF刷刷水题找自信 2
- android activity传值到dialog,android 自定义AlertDialog 与Activity相互传递数据
- django 学习-13 Django文件上传
- 专为专业音乐行业从业人员打造的AI智能编曲工具:Orb Producer Suite Mac
- 分布式存储系统Minio简介
- mysql不停库全量备份,mysql全量备份数据
- Python错误集锦:除法运算时提示ZeroDivisionError: division by zero
- HTML5实例教程:拼图游戏-何韬-专题视频课程
- 怎么让人物脚贴地 模型_3DMax人物模型关键帧,如图怎么把那红点的位置弄到脚后跟?...
- python绘图设置时间坐标轴_Matplotlib绘图双纵坐标轴设置及控制设置时间格式
- SpringBoot添加压力测试
- 华为荣耀play使用WiFi调试Android的坑
- 牛客网拼多多校招最大乘积
- 宇视摄像机网页界面登录“提示加载插件失败,点击下载安装最新插件”
- 【李佳辉_周报_2022.10.9】
- 大数据时代从繁乱冗杂中精准提取核心文本信息 × Python Tkinter 生成词云图
- torch.sequeeze 和 torch.unsequeeze 的用法