【问题标题】:shortest path to surround a target in a weighted 2d array在加权二维数组中围绕目标的最短路径
【发布时间】:2021-02-12 11:13:11
【问题描述】:

我很难找到正确的编码方法。

取一个随机生成的二维数组,大约 50x50,每个单元格的值是 1~99。 从随机位置“绿色”开始,目标是用最少的动作包围目标“红色”。
移动到相邻单元格需要 1~99 个动作,具体取决于它的值。
低值的小数组示例:

[

目前我最好的想法是,根据目标的对角线生成 4 组检查点,然后使用大量 Dijkstra 找到一条通过所有这些检查点的路径以及起点。

我遇到的一个问题是这很快就会变成极端数量的路径。
从“NorthWest-1 到 NW-20”的任何起点到“NE-1 到 NE-20”的任何终点,有 400 种可能性。将第 3 和第 4 对角线相加后变为 400 * 20 * 20。

使用对角检查点的另一个问题是问题不是[从绿色到对角线的最短路径(橙色路径)]

[

而是从“绿色到红色周围路径上的任何点”。

当前伪代码;

take 2 sets of diagonals nearest to Green/start
find the shortest path that connects those diagonals while going through Green
(backtracking through the path is free)

draw a line starting from the target point, in-between the 2 connected diagonals,
set those cells to value infinite to force going around them (and thus around the target)

find the shortest path connecting the now-seperated diagonals

不幸的是,这个伪代码已经包含了一些边缘情况,其中“墙”阻挡了最有效的路径。

如果相关,这将用 javascript 编写。

编辑,作为一种边缘情况,它可以在包围之前使目标螺旋,虽然非常罕见

编辑2; “包围”是指将目标与场的其余部分断开,无论包围的区域有多大,或者即使它包括起点(例如,所有边都是0)

这是另一个具有(可能)最佳路径的较大字段,以及文本形式的 2 个字段:
https://i.imgur.com/yMA14sS.png
https://pastebin.com/raw/YD0AG6YD

【问题讨论】:

  • 有趣的一个。我能想到的一种方法是将其分为两个不同的问题:找到包含目标且成本最低的闭环。湾。从源头运行 BFS,直到找到在 a 中找到的闭环的一个单元格。第一个问题(a)当然是更难的一个。
  • 请您编辑问题以将您的测试用例的数据之一包含为代码(即二维数组)以便可以复制/粘贴?
  • 栅栏有两个侧面。围绕起始节点的栅栏是否也被视为“围绕”目标节点?如果不是,您能否澄清“环绕”的含义,即对于从目标节点断开连接的任何给定路径,哪些被认为是“环绕”目标,哪些不是?

标签: algorithm breadth-first-search pseudocode shortest-path dijkstra


【解决方案1】:

简而言之,让我们称之为围绕目标栅栏的路径。有效的栅栏是一组(连接的)节点,它使目标从一开始就断开连接,但不包括目标。最小的围栏是这样做的同时具有最低的成本。 lasso 可以是一个栅栏,其中包含到起始节点的路径。目标是构建成本最低的套索。

一个简单的算法是使用目标的直接邻域作为栅栏,并将 Dijkstra 运行到这些栅栏节点中的任何一个以构建(可能不是最佳的)套索。请注意,如果需要最佳答案,栅栏的选择实际上会影响从起点到栅栏的路径选择——反之亦然,从起点到栅栏的路径选择可以影响栅栏本身的选择方式。问题不能整齐地分成两部分。

我相信以下算法会产生最佳的栅栏

  1. 使用 Dijkstra 构建从起点到目标的路径(不包括终点)。让我们称之为黄色路径。
  2. 构建 2 组节点,在此 yellow 路径的每一侧,并与其相邻。将这些集合称为 redblue。请注意,对于与路径相邻的任何给定节点,它可以是路径的一部分、蓝色集、红色集,或者实际上是一个端点。
  3. 对于 red 集合中的每个节点,运行 Dijkstra 以找到 blue 集合中 not 交叉的节点的最短路径黄色路径。
  4. 对于之前的每条路径,在添加(缺失的)黄色路径位以将蓝色和红色端连接在一起后,查看哪个最短。

费用为length(yellowPath) * cost_of_Dijkstra(redStart, anyBlue)

要制作一个好的套索,从头开始运行 Dijkstra 到任何栅栏节点就足够了。 但是,我不确定最终的 lasso 是否是最优的

【讨论】:

  • 这似乎是一个很好的解决方案,目前正在对其进行编码以查看详细信息。 ---而不是目标,我可能会dijkstra到目标“后面”的一个单元格(从一开始就看),这可能会更准确一些? ---“红色和蓝色”需要一些调整,而不是使用节点,只有黄色路径和“红色边界单元”之间的边界需要转向 1 路 --- 否则当路径螺旋时会产生问题左右 --- 最后,需要有一堵墙,这样红蓝就不会围绕起点。需要一段时间来编码:)
  • 嗯,对。如果一个节点既是红色又是蓝色,那么您必须将其处理为像两者一样,并在第 4 步计算中充当“封闭在 0”。我认为“落后”目标的路径没有意义,因为最短路径可能包括也可能不包括任何给定的“落后”
【解决方案2】:

您可能需要考虑使用 A* 搜索算法,您可以调整算法以一次搜索所有 4 个点。

https://en.wikipedia.org/wiki/A*_search_algorithm

基本上,A* 扩展了 Dijkstra 的算法,将其搜索重点放在离目的地“更近”的地点。

搜索算法还有许多其他变体,可能对您的情况更有用,“另请参阅”部分中也有,但其中一些更适合视频游戏路径规划而不是 2D 网格路径。

再次查看问题后编辑:

似乎每个点都有重量。这使得距离计算变得不那么简单。在这种情况下,我会将其视为优化。对于启发式成本函数,最好只使用到达目标的最直接路径(对角线)作为启发式成本,然后只使用 A* 搜索来尝试找到更好的路径。


至于环绕逻辑。我会将其视为自己的逻辑和单独的步骤(可能是第二步)。首先找到到达目标的最低成本路径。然后找到最便宜的方法来环绕路径。老实说,围绕一个点最便宜的方法可能值得它自己提出问题。

一旦你拥有了这两个部分,就应该很容易合并这两个部分。两者首先会在某个点重叠,这就是它们合并在一起的地方。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多