用于 A* 搜索的启发式以收集 2D 网格中的最大硬币数?

Heuristic for A* search to collect the maximum number of coins in a 2D grid?

给定 NxM 网格的描述(起始单元格、目标单元格、无法到达的单元格、有硬币的单元格)使用 A* 寻路算法从起始单元格遍历网格到目标单元格,同时根据以下限制收集最大可能数量的硬币

1- Use only horizontal and vertical movement, diagonal movement is not allowed.
2- Each cell can be visited at most once.
3- Each cell can have at most 1 coin. 

举个例子(0表示空单元格,1表示有硬币的单元格,X表示无法到达的单元格,S是起始单元格,D是目标单元格):

S , X , X , X , X , X , X , X

1 , X , X , X , X , X , X , X

0 , X , X , X , X , X , X , X

1 , 1 , 1 , X , X , 0 , 1 , 0

0 , X , 0 , X , X , 0 , X , 0

0 , X , 0 , 1 , 1 , 1 , X , 1

0 , 1 , 0 , 0 , 0 , 0 , 0 , D

最佳路径单元格是粗体

请注意,我对解决方案的实际实施不感兴趣,我只想帮助找到合适的启发式函数来正确建模此问题。

tldr; A* 和最大化个数:可能但不好

第一个问题是定义适当的距离。

让状态为网格中的位置+被选中的数量。

邻居很简单,相邻的方块不是X

我们可以摆出远距离的姿势

d(a,b) = -(b.ones - a.ones)
  • 所以对于邻居b,如果我们选择一个1,距离是-1
  • 如果没有选择则 0

最小化 d 将产生最大数 1。

关于启发式,为了确保最佳解决方案,我们需要 h 可接受的,我们可以定义 h h(s) = -56(您的网格是 7x8)、h(s) = 56 - s.ones 甚至 h(s) = numberOfOnesInTheGrid - s.ones (虽然后者意味着我们事先知道有多少1s

然而 这不适合 A* 因为:

  • 我们想探索 所有 paths/states 当 A* 的目标是避免...
  • 我们将自己暴露在循环中(我们会贪婪地吃到……很久)。这是有症状的,不会发生在最短路径问题(具有正加权边)中,因为 循环 总是导致更长的路径被丢弃
  • 我们想要的本质上是最长路径问题而不是最短路径问题(例如到 D 的欧氏距离与最大化 1 的数量(或条件为 1 的访问状态的数量))。

恐怕A*不会有满意的结果。 显示问题的更简单的网格(从您的示例中提取):

0 , 1 , 0
0 , X , 0
S , X , 1
0 , 0 , D 

上面的路径较长(就访问的方块而言)但是是最佳路径

您始终可以通过将访问过的 path/states 存储到每个状态(以避免循环)来强制执行 A*,但您也可以只使用具有启发式的 dfs,首先使用 1