我正在开展一个项目,我需要执行路径查找以找到花费最少的路径。我真的不在乎它是否是最短的路线。到目前为止,似乎A *是不可能的,老实说,我不理解Prim的算法。
让我解释一下我需要找到路线的那种地图。这是一个示例地图:
+------|-*----
+------|----|-
+--|--------|-
+@-|----------
“*”是起始位置,“@”是目的地。一行中的“+”符号表示a)成本与单步相同的直接路线,b)整个路线的成本减半。
这意味着通过“+”路线从起始位置到目的地有10个“步骤”,最终成本为5.有15个步骤使用最左边的“|” route(“|”的成本低于“ - ”,但差于“+”),最终成本为15.显然,成本为5的路由是使用路径。
现在我在C#中实现它时遇到了麻烦。我目前有一个“步进”功能,如果方式被阻止或步骤的成本和新位置,它会移动并返回。这很好用,但目前它非常天真,因为它会下降到“|”如果它在“+”之前找到一个(这意味着整个行程的成本要高得多,因为它没有找到更快的路线)。
我正在考虑将每个位置标记为“已访问”,但是最低成本的路线将自行循环,这是完全合理的。还有许多不同的路径,每个路径都是唯一的,并且每个路径可以使用不同的路径段(可能已经被先前的运行访问过)。显然,每条路径都需要遍历才能找到最便宜的路径,但我无法弄清楚如何做到这一点,而不会一遍又一遍地搜索相同的路径。
如果它变得更简单,我可以限制任何移动仅移动到目的地(即,在下降后不能再次恢复)。
如果有人能提供一些见解,那就太好了!
答案 0 :(得分:4)
根据我的理解,地图中的' - '字段是图形节点。每个' - '节点最多有8个边到相邻的' - '字段。 8如果允许对角线移动,否则只有4个相邻的“ - ”节点有效。 ' - '节点和'|'之间没有边缘节点
这足以实现一个简单的深度优先搜索/广度优先搜索,其中您保留一个未监视节点的队列(LIFO用于深度优先,FIFO用于广度优先)和一个访问节点列表(到避免骑自行车)。两种算法都是相对低效的,但可以很容易地进行改进。
我不确定'+'节点的含义是什么。从一个'+'移动到下一个'+'模式是一个自由行动?如果是这样,您可以使用边缘成本对此进行建模。从' - '节点移动到' - '节点的成本为1,从'+'到'+'节点的移动成本为0.
广度优先搜索算法可以扩展到Dijkstra算法,只要所有图形边缘都是非负的,就可以计算源和目标之间的最短路径:
http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
通过添加简单的启发式算法可以进一步改进Dijkstra算法,使其成为A* algorithm。如果您在2D坐标中具有目标坐标,则可以使用节点与目标之间的欧几里德距离作为最佳遵循哪个节点的粗略估计。如果'+'字段是通过地图的隧道,移动成本为零,那么A *算法可能没有那么多帮助,因为如果您应该移向隧道,启发式移动到目的地通常是错误的。如果有多个隧道或隧道未通往目的地,则可能没有比天真Dijkstra算法更好的启发式算法。
请注意,成本最低的路由不可能包含一个循环:如果成本最低的路由包含一个循环,剥离循环仍然会产生一个有效的路径到目标,成本较低与我们的假设相矛盾从成本最低的路线开始。
查看Cormen's Introduction to Algorithms或相关的维基百科页面:
http://en.wikipedia.org/wiki/Shortest_path
http://en.wikipedia.org/wiki/Breadth-first_search