计蒜客 OJ,https://nanti.jisuanke.com/t/T1214。
已知一张地图(以二维矩阵的形式表示)以及佐助和鸣人的位置。地图上的每个位置都可以走到,只不过有些位置上有大蛇丸的手下,需要先打败大蛇丸的手下才能到这些位置。鸣人有一定数量的查克拉,每一个单位的查克拉可以打败一个大蛇丸的手下。假设鸣人可以往上下左右四个方向移动,每移动一个距离需要花费 1 个单位时间,打败大蛇丸的手下不需要时间。如果鸣人查克拉消耗完了,则只可以走到没有大蛇丸手下的位置,不可以再移动到有大蛇丸手下的位置。佐助在此期间不移动,大蛇丸的手下也不移动。请问,鸣人要追上佐助最少需要花费多少时间?
输入的第一行包含三个整数:M,N,T。代表 M 行 N 列的地图和鸣人初始的查克拉数量 T。0 后面是 M 行 N 列的地图,其中 @ 代表鸣人,+ 代表佐助。* 代表通路,# 代表大蛇丸的手下。 输出包含一个整数 R,代表鸣人追上佐助最少需要花费的时间。如果鸣人无法追上佐助,则输出 −1。 一个 M*N 大小的迷宫,我们从 @ 位置出发(也就是起点),字符 * 表示可以安全通行的方格,字符 # 表示有怪物(可以杀死,但是需要付出代价),字符 * 表示仙药(也就是终点)。要求输出从 @ 到 * 的最短路径。那么迷宫问题的基本要素全齐了,所以本题就是一道 BFS 模板题。 和上一题,https://blog.csdn.net/justidle/article/details/104662118,最大的不同是在于:杀死大蛇丸的手下是需要付出代价的,也就是所谓的查克拉。而题目提供的查克拉是有限的。因此本题最大的变化就是如何表示查克拉的变化。 对于 # 表示的地点,我们有两种操作。第一种,查克拉够,我们可以杀死大蛇丸的手下,通过这个地方。第二种查克拉不够,那么意味着这里不能通过,需要绕道。如何表示查克拉,是本题最大的变化。因为某个位置导致查克拉变化后,其后所有状态都会发生改变。所以我们将 visit 数组从二维变为三维,也就是最后一维表示不同查克拉状态的访问性。 如果想看类似的数据分析,可以看以前的文章,https://blog.csdn.net/justidle/article/details/104651311。主要是我偷懒了,画图太累了,请原谅。 1、读入数据,并写入到合适的数据结构中。 2、找到起点位置,将起点加入到队列 q 中。 3、记录终点位置信息。 4、开始 BFS 遍历。直到找到终点或者遍历所有节点而无法到达终点。碰到 # 的道路,需要判断查克拉。 1、由于有查克拉的存在,每个结点需要增加查克拉信息记录。代码部分如下: 2、关于 # 的处理。注意代码中对通过性的判断。以前题目中,我们是将本节点能否走和其他条件一起判断。这里,我们需要分开判断,先判断其他条件,再判断是否为大蛇丸的手下(即 #)。代码部分如下:输出格式
样例输入1
4 4 1
#@##
**##
###+
****
样例输出1
6
样例输入2
4 4 2
#@##
**##
###+
****
样例输出2
4
题目分析
题意分析
样例数据分析
算法思路
AC 参考代码
#include
代码分析
struct POS {
int x, y;//坐标
int t;//查克拉数
int dis;//距离
};
if (maze.data[next.x][next.y]!='#') {
不是大蛇丸的手下,那么操作和以前一样
} else {
大蛇丸手下
先判断查克拉是否够用 cur.t>0
再判断查克拉减 1 后是否访问过 maze.visit[next.x][next.y][cur.t-1]==false
}