广度优先搜索——动态类迷宫问题

动态类迷宫中通常会出现其中一些特殊的物品,按一定周期进行变化。

我们假设迷宫中有一个楼梯,且是动态的,每隔一个单位时间,楼梯就会变换一次方向。楼梯的形状在开始时为 ‘-’ 或 ‘|’,表示其连接横向上的两个格子或纵向上的两个格子。 而当梯子转到另一方向(纵向)时,垂直于梯子方向(横向)是无法通行的。在此问题中允许蒜头君停留在某个除梯子的可行位子。
动态迷宫的具体输入为第一行 n 和 m 表示迷宫的行数和列数。接下来是一个 N 行 M 列的地图,‘*‘表示障碍物,’.‘表示走廊,’|’ 或者 ‘-’ 表示一个楼梯,并且标明了它在一开始时所处的位置:‘|‘表示的楼梯在最开始是竖直方向,’-’ 表示的楼梯在一开始是水平方向。地图中还有一个 ‘S’ 是蒜头君的位置,'T’是目标,0≤ N,M≤10,地图中不会出现两个相连的梯子。蒜头君每秒只能停留在 ‘.’ 或 ‘S’ 和 ‘T’ 所标记的格子内。

我们在分析这道题目时,我们发现整个迷宫的题字的周期是一致的,说明整个地图本质上只有两种状态,即奇数时间状态和偶数时间状态。
那么我们有什么策略吗?本质上,我们可以将一个位置分为两种状态考虑。分别记录一个位置上,奇数时间和偶数时间是否访问。那么对于之后的题目,如果整个迷宫的变化周题为T,那么我们也能够同样将一个位置拆分为T种状态。
对于这道题,我们拥有更巧妙的方案,实际上我们如果发现路径上需要通过梯子,且恰好再那个时刻梯子在另一个方向上,最直观的方案就是等待一个单位时间。其实这个等待操作也代表之前2种状态转化。

pause表示当前位置有没有停过。
我们需要枚举的是:

原本:u.x,u.y,u.tm,u.pause
当u.pause=false时
要枚举的是:
u.x+1,u.y,u.tm,u.pause=false
u.x-1,u.y,u.tm,u.pause=false
u.x,u.y+1,u.tm,u.pause=false
u.x,u.y-1,u.tm,u.pause=false
u.x,u.y,u.tm,u.pause=true
当然,在u.pause=true时
最后一种情况就不用了,只用枚举前4种即可

还有判断一下这个地方能不能走以及是否被访问过(前四种情况)

我们首先要处理遇到地图上的楼梯。对于纵向楼梯,我们需要分当前运动方向讨论。当我们横向运动时,只能在奇数时间通过;当我们以纵向运动时,我们只能在偶数时间通过。另外,由于梯子的特殊性,如果当前时间是可以通行,那么需要继续移动1格.

两种梯子就应该是:
在|的情况下,有两种情况,没有翻转时的坐标就应该是把x轴上的数-2,翻转后就应该是把y轴上的数+2。
在-的情况下,也有两种情况,没有翻转时的坐标就应该是把y轴上的数-2,翻转后就应该是把x轴上的数+2。
别忘了,最后还要处理最重要的停留操作,当然也很简单,就是当前如果还没停过,就让它停一次即可。
示例代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#in
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值