diff --git a/src/SUMMARY.md b/src/SUMMARY.md index f4d1e3f..ec24e6f 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -12,7 +12,7 @@ - [搜索策略 🚧](solver/solving_strategy.md) - [启发式函数 🚧](solver/heuristic_function.md) - [优化](solver/optimization.md) - - [隧道]() + - [隧道](solver/tunnels.md) - [死锁 🚧](solver/deadlocks.md) - [割点]() - [双向搜索]() diff --git a/src/solver/assets/tunnel_pattern_1.png b/src/solver/assets/tunnel_pattern_1.png new file mode 100644 index 0000000..0e82685 Binary files /dev/null and b/src/solver/assets/tunnel_pattern_1.png differ diff --git a/src/solver/assets/tunnel_pattern_2.png b/src/solver/assets/tunnel_pattern_2.png new file mode 100644 index 0000000..8cbf24b Binary files /dev/null and b/src/solver/assets/tunnel_pattern_2.png differ diff --git a/src/solver/tunnels.md b/src/solver/tunnels.md index 5e1397c..909e0ce 100644 --- a/src/solver/tunnels.md +++ b/src/solver/tunnels.md @@ -1,49 +1,31 @@ # 隧道(Tunnels) -TODO: 图片: 分支后又合并, 说明为何无影响力推动可以被跳过. -TODO: 说明何为隧道. - 一般情况下, 箱子的移动将产生一个新的状态, 该状态还会包含其他箱子移动所产生的子状态, 这是因为箱子之间可能存在相互影响. 但在部分关卡中, 存在一种被称为**隧道**的结构, 可以将位于隧道内的箱子与隧道外的箱子**隔绝**, 使它们之间互不影响. -![](assets/tunnel.png) +![隧道](assets/tunnel.png) 如上图所示, 当上方的箱子位于隧道时, 两个箱子之间不会产生影响. 此时推动隧道内的箱子被视作**无影响力推动**(No influence pushes). 在有 $n$ 个箱子的关卡中, 每一个状态最多有 $n$ 个子状态. 但如果当前状态是无影响力推动, 则无需产生子状态, 应该继续推动箱子, 直到产生有影响力的推动(一般是该箱子离开隧道), 并产生 1 个子状态. -TODO: 考虑隧道内存在目标的情况 - -当玩家推动箱子后产生以下模式, 则应该往同方向继续推一次. -TODO: 说明原因 - -TODO: 是否满足容许性? - -```txt -########### -#. $@$ .# -########### -``` - ## 停放 将箱子推入隧道内的推动是有影响力的, 这意味这将该箱子停放到隧道内, 并为玩家和其他箱子的移动腾出空间. -TODO: 说明隧道中可以停放一个箱子, 在隧道的入口处, 或出口前. 但应该只停靠在入口处, 因为这样更高效. 说明为何更高效. +单个隧道内**最多能停放一个箱子**. 因为隧道中是不存在目标的, 停放多个箱子会产生[畜栏死锁], 进而导致关卡无解. -为了避免[畜栏死锁], 隧道内**最多能停放一个箱子**. -如果将箱子停放在隧道出口处, 则玩家还需要从隧道入口处离开隧道. 而将箱子停放在隧道入口处, 玩家设置无需进入隧道. +隧道内**停放箱子的最佳位置是隧道入口**, 此处的隧道入口指的是距离箱子最近的隧道口. +因为如果停放在隧道的其他位置, 玩家还需要重新返回隧道入口才能离开封闭的隧道, 这意味着玩家需要原路返回, 增加了不必要的移动步数. -如果箱子停留在隧道出口则玩家需要 +## 识别 ---- +若推动后产生了如下的模式(包括旋转和镜像), 则表示箱子已经被推入隧道, 属于无效推动. 此时应该继续推动箱子, 直到箱子离开隧道, 产生具有有效推动的子状态. -若推动后产生了如下的模式, 包括旋转和镜像. +![隧道模式 1](assets/tunnel_pattern_1.png) +![隧道模式 2](assets/tunnel_pattern_2.png) -```txt -#$ #$# -#@# #@# -``` +下面是计算隧道的实现, 通过遍历地图, 识别符合 2 种隧道模式(包括镜像和旋转)的位置并进行标记. 计算结果可以被缓存, 以便在后续求解过程中快速判断隧道. ```rs impl Solver { @@ -111,3 +93,7 @@ impl Solver { ``` [畜栏死锁]: deadlocks.md#畜栏死锁corral-deadlocks + +## 参考 + +- .