题目相关

题目链接

计蒜客 OJ,https://nanti.jisuanke.com/t/T1213。

题目描述

公主被恶人抓走,被关押在牢房的某个地方。牢房用 N×M(N,M≤200) 的矩阵来表示。矩阵中的每项可以代表道路(@)、墙壁(#)、和守卫(x)。

英勇的骑士(r)决定孤身一人去拯救公主(a)。我们假设拯救成功的表示是 "骑士到达了公主所在的位置"。由于在通往公主所在位置的道路中可能遇到守卫,骑士一旦遇到守卫,必须杀死守卫才能继续前进。

现假设骑士可以向上、下、左、右四个方向移动,每移动一个位置需要 1 个单位时间,杀死一个守卫需要花费额外的 1 个单位时间。同时假设骑士足够强壮,有能力杀死所有的守卫。

给定牢房矩阵,公主、骑士和守卫在矩阵中的位置,请你计算拯救行动成功需要花费最短时间。

输入格式

1、两个整数代表 N 和 M,(N,M≤200).
2、随后 N 行,每行有 M 个字符。"@" 代表道路,"a" 代表公主,"r" 代表骑士,"x" 代表守卫, "#" 代表墙壁。

输出格式

如果拯救行动成功,输出一个整数,表示行动的最短时间。
如果不可能成功,输出 "Impossible"。

样例输入1

7 8
#@#####@
#@a#@@r@
#@@#x@@@
@@#@@#@#
#@@@##@@
@#@@@@@@
@@@@@@@@

样例输出1

13

样例输入2

13 40
@x@@##x@#x@x#xxxx##@#x@x@@#x#@#x#@@x@#@x
xx###x@x#@@##xx@@@#@x@@#x@xxx@@#x@#x@@x@
#@x#@x#x#@@##@@x#@xx#xxx@@x##@@@#@x@@x@x
@##x@@@x#xx#@@#xxxx#@@x@x@#@x@@@x@#@#x@#
@#xxxxx##@@x##x@xxx@@#x@x####@@@x#x##@#@
#xxx#@#x##xxxx@@#xx@@@x@xxx#@#xxx@x#####
#x@xxxx#@x@@@@##@x#xx#xxx@#xx#@#####x#@x
xx##@#@x##x##x#@x#@a#xx@##@#@##xx@#@@x@x
x#x#@x@#x#@##@xrx@x#xxxx@##x##xx#@#x@xx@
#x@@#@###x##x@x#@@#@@x@x@@xx@@@@##@@x@@x
x#xx@x###@xxx#@#x#@@###@#@##@x#@x@#@@#@@
#@#x@x#x#x###@x@@xxx####x@x##@x####xx#@x
#x#@x#x######@@#x@#xxxx#xx@@@#xx#x#####@

样例输出2

7

题目分析

题意分析

一个 N*M 大小的迷宫,我们从 r 位置出发(也就是起点),字符 @ 表示可以安全通行的方格,字符 # 表示墙壁(也就是不能走),字符 x 代表守卫(守卫可以杀死,但是必须付出额外的 1 个单位时间),字符 a 表示仙药(也就是终点)。要求输出从 @ 到 a 的最短路径。那么迷宫问题的基本要素全齐了,所以本题就是一道 BFS 模板题。

样例数据分析

本题和以前的 BFS 模板题唯一的不同就是所有守卫可以杀死,但是需要付出额外的时间。因此意味着 x 的地方是可以走的,只是要多付出 1 个单位时间。也就是说,走 x 地方,需要 2 个时间单位;走 @ 地方,需要 1 个时间单位。

省略。如果想看类似的数据分析,可以看以前的文章,https://blog.csdn.net/justidle/article/details/104651311。主要是我偷懒了,画图太累了,请原谅。

算法思路

1、读入数据,并写入到合适的数据结构中。

2、找到起点位置,将起点加入到队列 q 中。

3、记录终点位置信息。

4、开始 BFS 遍历。直到找到终点或者遍历所有节点而无法到达终点。注意:走 x 地方,需要 2 个时间单位;走 @ 地方,需要 1 个时间单位。

AC 参考代码

#include <cstdio>
#include <queue>//位置定义
struct POS {int x, y;//坐标int cost;//本节点到起点的距离
};const int MAXN = 202;
struct MAZE {int row, col;//迷宫大小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.row, &maze.col);//读入迷宫数据int i,j;for (i=0; i<maze.row; i++) {for (j=0; j<maze.col; j++) {scanf(" %c", &maze.data[i][j]);if (maze.data[i][j]=='a') {//终点maze.x2 = i;maze.y2 = j; } else if (maze.data[i][j]=='r') {//起点maze.x1 = i;maze.y1 = j; }}} int ans = bfs(maze);if (ans>0) {printf("%d\n", ans);} else {printf("Impossible\n");}return 0;
}int bfs(MAZE &maze) {std::queue<POS> q;//下一个节点队列const POS move[] = {{-1,0}, {0,1}, {1,0}, {0,-1}};//骑士的移动方法POS cur;//当前位置POS 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();if (maze.data[cur.x][cur.y]=='x') {//由于有干掉守卫,所以我们我们先加入的不一定是最小的maze.data[cur.x][cur.y]='@';cur.cost++;q.push(cur);} else {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.row&&next.y>=0&&next.y<maze.col&&maze.visit[next.x][next.y]==false&&maze.data[next.x][next.y]!='#') {next.cost = cur.cost + 1;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

(4)判断这个位置是不是守卫。在弹出队首元素的时候才判断。如下所示:

if (maze.data[cur.x][cur.y]=='x') {//由于有干掉守卫,所以我们我们先加入的不一定是最小的maze.data[cur.x][cur.y]='@';cur.cost++;q.push(cur);
}

当然,也可以在走到本位置的时候进行判断。不管在哪里判断,是不会影响结果的,这是由于 BFS 的特性决定的。

计蒜客题解——T1213:拯救行动相关推荐

  1. 计蒜客题解——T1414:抠图

    题目相关 题目链接 计蒜客,https://nanti.jisuanke.com/t/T1414. 我的 OJ,http://47.110.135.197/problem.php?id=4768. 题 ...

  2. 计蒜客题解——T1214:鸣人和佐助

    题目相关 题目链接 计蒜客 OJ,https://nanti.jisuanke.com/t/T1214. 题目描述 已知一张地图(以二维矩阵的形式表示)以及佐助和鸣人的位置.地图上的每个位置都可以走到 ...

  3. 计蒜客题解——T1769:最大岛屿

    题目相关 题目链接 计蒜客,https://nanti.jisuanke.com/t/T1405. 我的OJ,http://47.110.135.197/problem.php?id=5254. 题目 ...

  4. 计蒜客题解——T1244:单词序列

    题目相关 题目链接 计蒜客 OJ,https://nanti.jisuanke.com/t/T1244. 我的 OJ,http://47.110.135.197/problem.php?id=4766 ...

  5. 计蒜客题解——最大的余数

    其实本题的难度真心不高,但是可以完整说明数据分析.标程.随机数生成.对拍等部分. 题目链接 原题来自计蒜客的某次比赛.计蒜客对应的链接为https://nanti.jisuanke.com/t/422 ...

  6. 计蒜客题解——T1157:派

    题目相关 题目链接 计蒜客,https://nanti.jisuanke.com/t/T1157. 我的OJ,http://47.110.135.197/problem.php?id=4951. 题目 ...

  7. 计蒜客题解-T1260宗教信仰

    题目概况 链接: https://nanti.jisuanke.com/t/T1260 难度: 普及/提高-(计蒜客评级普及T3,个人评价T2) 题目分析 简化题目: 有几群人,分别信仰不同的宗教,有 ...

  8. 计蒜客2020蓝桥杯大学A组模拟赛题解

    计蒜客2020蓝桥杯大学A组模拟赛题解 蓝桥杯的话,去年拿了C++组的国二.今年报名了新成立的Python组,不知道能不能摸到国一的鱼 模拟赛链接如下: https://www.jisuanke.co ...

  9. 计蒜客一月入门赛:《三个火枪手》题解

    题目链接(https://nanti.jisuanke.com/t/52314) 有 n 个人,其中有 m 对相互认识的关系. 一个人的知名度定义为 有多少人 和他相互认识. 现在蒜头君需要从这 n ...

最新文章

  1. 【cocos2d-x】游戏构成要素②----使用多个层
  2. eclipse查看Android应用内存使用情况
  3. E - Counting Cliques HDU - 5952
  4. 【Trie】阅读理解(luogu 3879/ybtoj Trie-4)
  5. linux虚拟机怎么看var文件,一种获取Linux虚拟机内部日志的方法
  6. 列表操作 - C#开发人员
  7. DNS(BIND) 正向解析   反向解析 基本服务的搭建
  8. netfilter数据流图 | 转
  9. python pca双标图的含义_PCA双标图 - 箭长度
  10. 象棋软件最强手机版_我说它是地表手机最强清理软件,没意见吧
  11. linux 9 -- 交互式使用Bash Shell
  12. 「教程」Windows程序未响应,怎么分析确认具体原因
  13. SpringBoot集成Shiro管理会话和权限
  14. 杀毒软件巨头荣光不复 瑞星信息去年亏损7300万元
  15. 自己对香港一卡通的总结
  16. C基础(三)函数的使用
  17. 第17天 命令行窗口
  18. 2021北京大学暑期课程:区块链与隐私计算
  19. 什么是BSP? 概念解析
  20. 51假期读书笔记(下)——流畅的python

热门文章

  1. 云原生,炸裂!(文末有福利)
  2. thinkphp6对接阿里云短信服务完成定时发送短信功能
  3. qt 设置背景图片、背景色步骤
  4. 笔记本电脑移动办公平台网络解决方案
  5. 北航计算机学院李卫国,北航学生评选“心目中最爱戴的老师”
  6. Unity使用Package Manager管理自定义插件
  7. Mockito Verify的使用
  8. web端引入高德地图
  9. python桌面_python写桌面
  10. 半导体公司----仙童、英特尔、AMD