我知道Dijkstra的算法可以找到两个节点之间的最小距离(或者在地铁站的情况下)。我的问题是关于找到两个站之间的最小转移次数。而且,在所有最小传输路径中,我想要具有最短时间的传输路径。
现在为了找到最小传输路径,我使用了应用于地铁线路的专用BFS,但它并不能保证找到的路径是所有其他最小传输路径中最短的路径。
我在想,也许修改Dijkstra的算法可能会有所帮助 - 通过启发式地为每次转移增加权重(时间),这样就可以阻止算法转移到不同的行。但在这种情况下,我需要根据经验找到转移权重。
除了问题:
我建议每次算法想要转移到不同的地铁线路时添加“惩罚”。在这里,我解释一下我对此的一些担忧。
我把这个问题推迟了几天,今天又回到了它。在再次查看问题之后,看起来在车站上进行Dijkstra算法并确定转移发生的位置很难,这并不像人们想象的那么明显。
这是一个例子:
如果在这里我有一个局部图(只有4个站)和他们的地铁线:A(红色),B(红色,蓝色),C(红色),D(蓝色)。让A站成为源。
连接是:
---- D(蓝色) - B(蓝色,红色) - A(红色) - C(红色)-----
如果我遵循Dijkstra算法:最初我将A放入队列,然后在第一次迭代中将A出列并查看其邻居: B和C,我根据权重A-B和A-C更新它们的距离。现在即使B连接两条线,此时我也不知道 如果我需要在B进行转移,那么我不会为转移添加“惩罚”。 假设A-B与A-B之间的距离为1。 A-C,它导致B的下一次迭代出列。它的邻居是D,只有在此 我看到转移必须在B处进行。但B已经处理(出列)。小号
所以我不确定这种“延迟”在确定转移需求时会如何影响算法的完整性。 有什么想法吗?
答案 0 :(得分:4)
您可以将每个权重设为一对:(# of transfers, time)
。您可以以显而易见的方式添加这些权重,并按字典顺序进行比较(首先比较传输次数,使用时间作为决胜局)。
当然,正如其他人所提到的,只要你知道apriori的最大时间并且你的体重存储中没有用完的东西,使用K * (# of transfers) + time
来获得足够大的K会产生相同的效果。 / p>
答案 1 :(得分:2)
我将使用 A* Algorithm 来描述我的解决方案,我认为这是Dijkstra算法的扩展(并且是一种改进 - 请不要拍我)这更容易直观地理解。它的基础是这样的:
您可以使用两个权重:停止和距离/时间,而不是将您的体重简单地放在距离远至目标的最小距离上,而不是这样:
基本上,比较:
以这种方式排序你的队列。
如果你曾经玩过Mario Party,可以考虑将星座和距离视为硬币。在游戏中间,一个拥有两颗星和十颗硬币的人将会超过拥有一颗星和五十枚硬币的人。
这样做可以保证您从优先级队列中取出的第一个节点将是可能停止次数最少的级别。
答案 2 :(得分:1)
你有正确的想法,但你并不需要根据经验找到转移重量 - 你必须确保单次转移的重量大于最长旅行时间的重量。如果您给转移的重量相当于一年的旅行时间,那么您应该非常安全。
答案 3 :(得分:1)
正如Amadan在评论中指出的那样,一切都是关于创建正确的图形。我将更详细地描述它。
如果它们在一条线上,则考虑两个顶点(站)具有边缘。使用此图(和权重1),您将找到Dijkstra的最小转换次数。
现在,让我们假设最长旅行时间总是少于10000(使用你的常数)。然后,边AB的重量(A和B在一条线上)是time_to_travel_between(A, B) + 10000
。
在这样的图表上运行Dijkstra将保证使用最少数量的转换,并在第二位达到最短时间。
评论上的更新 让我们“证明”它。有两个解决方案:2次转机和40分钟的旅行时间,3次转机和25分钟的旅行时间。在第一种情况下,你行3线,所以路径重量将是3 * 10000 + 40.第二种:4 * 10000 + 25.将选择第一种解决方案。
答案 4 :(得分:0)
直到现在我和你有同样的问题。我在使用Dijkstra。转移的处罚确实是一个非常好的主意,我现在已经使用了一段时间。主要问题是您不能直接在重量中使用它,因为您首先必须确定转移。而且我不想修改算法。
所以我一直在做的是,每次你找到转移,删除节点,添加惩罚权重并重新运行图表。
但是这样我发现Dijkstra不会工作。这就是我尝试Floyd-Warshall的地方,它与Dijkstra相反,比较了每对顶点之间通过图表的所有可能路径。
它帮助我改变了Floyd-Warshall的问题。希望它也能帮到你。 它更容易编码,更容易实现。