1

我正在做一个项目,我需要执行寻路以找到成本最低的路线。我真的不在乎这是否是最短的路线。到目前为止,似乎 A* 是不可能的,老实说,我不了解 Prim 的算法。

让我解释一下我需要在哪些地图上查找路线。这是一个示例地图:

+------|-*----
+------|----|-
+--|--------|-
+@-|----------

“*”是开始位置,“@”是目的地。一行中的“+”号表示一条直接路线,它 a) 与单个步骤的成本相同,b) 整个路线的成本减半。

这意味着从起始位置通过“+”路线到目的地有 10 个“步骤”,最终成本为 5。使用最左边的“|”有 15 个步骤 路由(“|”的成本比“-”低,但比“+”差),最终成本为15。显然,成本为5的路由是要使用的路由。

现在我无法在 C# 中实现它。我目前有一个“步进”函数,如果路径被阻塞或步进成本以及新位置,它会移动并返回。这很好用,但目前它非常幼稚,因为它会下降一个“|” 如果它在“+”之前找到一个(这意味着整个行程的成本要高得多,因为它没有找到更快的路线)。

我正在考虑将每个位置标记为“已访问”,但完全有可能最低成本的路线会自行循环。还有许多不同的路径,每一个都是唯一的,并且每一个都可能使用不同的路径段(可能已经被之前的运行访问过)。显然,需要遍历每条路径才能找到最便宜的路径,但如果不一遍又一遍地搜索相同的路径,我无法弄清楚如何做到这一点。

如果它使它更简单,我可以将任何运动限制为仅向目的地移动(即,下降后不能再次返回)。

如果有人能提供一些见解,那就太好了!

4

1 回答 1

4

据我了解,地图中的“-”字段是图形节点。每个“-”节点到相邻的“-”字段最多有 8 条边。如果允许对角线移动,则为 8,否则只有 4 个相邻的“-”节点有效。'-' 节点和 '|' 之间没有边 节点。

这足以实现简单的深度优先搜索/广度优先搜索,您可以在其中保留未访问节点的队列(深度优先为 LIFO,广度优先为 FIFO)和已访问节点列表(以避免循环) . 两种算法的效率都相对较低,但可以轻松改进。

我不确定您的“+”节点的含义是什么。从一个“+”移动到下一个“+”模式是自由移动吗?如果是这样,您可以使用边缘成本对此进行建模。从或到“-”节点的移动成本为 1,从“+”到“+”节点的移动成本为 0。

广度优先搜索算法可以扩展到 Dijkstra 算法,只要所有图形边都是非负的,该算法就会计算源和目标之间的最短路径:

http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm

Dijkstra 算法可以通过添加一个简单的启发式进一步改进,使其成为A* 算法。如果您有 2D 坐标中的目标坐标,则可以使用节点与目标之间的欧几里德距离来粗略估计最好遵循哪个节点。如果“+”字段是通过地图的隧道,移动成本为零,则 A* 算法可能没有太大帮助,因为如果您应该向隧道移动,那么启发式地向目的地移动通常是错误的。如果有多个隧道或隧道未通向您的目的地,则可能没有比朴素 Dijkstra 算法更好的启发式算法了。

请注意,成本最低的路线不可能包含环路:如果最低成本的路线包含环路,那么剥离环路仍会产生到达目标的有效路线,成本较低,这与我们从成本最低的路线。

查看Cormen 的算法简介或相关的 Wikipedia 页面:

http://en.wikipedia.org/wiki/Shortest_path

http://en.wikipedia.org/wiki/Breadth-first_search

http://en.wikipedia.org/wiki/Depth-first_search

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

于 2009-11-25T09:08:17.197 回答