我正在尝试实现“6 Degrees”式算法,因为我试图找到两个链接之间的最短路径。在这种情况下,它是一个视频游戏,它有区域地图,其中有相互链接的门户/经线。
每张地图都有一张地图ID int id
,并且可以有多个门户网站,实现为List<Portal>
。
每个门户网站都会将引导至地图int ToMapID
,并且包含地图Map HomeMap
。
无论如何,我已经成功地在两张地图之间找到了最少的数量的经线,这很好,因为这就是我想要的。问题是,我很难绕过如何记录从A点到B点的路径。
以下是我实施的内容:
Map start = allMaps[0];
Map end = allMaps[1];
int distance = 0;
List<Portal> alreadyChecked = new List<Portal>();
List<Portal> queue = start.Portals;
while (queue.Count > 0) {
distance++;
List<Portal> newQueue = new List<Portal>();
foreach (Portal p in queue) {
foreach (Portal tm in theMap.Portals) {
if (!alreadyChecked.Contains(tm)) {
alreadyChecked.Add(tm);
if (tm.ToMap == end.ID) {
Console.WriteLine("Found a path, it is " + distance + " map(s) away;");
Console.ReadKey();
Environment.Exit(0);
}
newQueue.Add(tm);
}
}
}
queue = newQueue;
}
理想情况下,我希望有一个Map[]
数组,其中包含从A点到B点的步骤顺序。
答案 0 :(得分:3)
当你newQueue.Add(tm);
时,你也应该记录你来自哪里。一个简单的解决方案是将关系添加到字典:dict.Add(tm,p)
。最后,您可以使用此词典通过简单地询问当前门户的父级来从目标向后走路径。
答案 1 :(得分:2)
最短路径基本上是这样的:
起点以零成本开始。所有其他区域都以无限远的成本开始。
维护可到达区域的队列。最初这只是起始区域。
遍历可到达的区域,始终选择成本最低的区域。
对于每个直接连接的区域,计算(成本+当前区域)+(连接经线点的成本)。如果这小于邻居区域的当前成本,则更新成本,设置指向当前区域的反向链接指针,并将其添加到队列中。
重复直到下一个要处理的区域(队列中的最低成本区域)的成本等于或大于目标区域。
然后,从目标区域,按照反向链接指针形成您的路径。
在所有链路具有相同成本的简单情况下,您可以只使用FIFO队列,它将保持排序。如果旅行费用有所不同,则必须按队名成本对队列进行排序。