【问题标题】:How to find minimum number of transfers for a metro or railway network?如何找到地铁或铁路网络的最少换乘次数?
【发布时间】:2010-06-29 02:55:35
【问题描述】:

我知道 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

所以我不确定这种确定传输需求的“延迟”会如何影响算法的完整性。 有什么想法吗?

【问题讨论】:

  • 如果这是作业,请在问题中添加[homework]标签。
  • 一个简单的答案是,如果你真的想要最少的传输,然后在最少的传输中最少的时间,只需让传输权重大于最大路径权重。
  • @Robert Harvey - 这不是一个家庭作业问题。 @Amadan - 您如何找到最大路径的权重?可以任意长。还是我误会了你?
  • @Amadan - 我明白你在说什么。抱歉,我的英语有时不太好。
  • 他表示图中两个最远节点之间的距离(行驶时间)。

标签: algorithm graph


【解决方案1】:

您可以将每个权重配对:(# of transfers, time)。您可以以显而易见的方式添加这些权重,并按字典顺序比较它们(首先比较传输次数,使用时间作为决胜局)。

当然,正如其他人所提到的,使用K * (# of transfers) + time 获得足够大的 K 会产生相同的效果,只要您知道最大时间先验并且不会用完权重存储中的位。

【讨论】:

  • 我喜欢权重对的想法。我认为这也可能有效。
  • 您可能还想根据将要发生的传输类型添加不同的权重。例如,地下到地下的换乘将具有较低的重量,因为地下定期运行(在我居住的城市,每 10 分钟最慢),而地下到公共汽车/手推车的换乘将是中等重量,而手推车/公共汽车到手推车/公共汽车转移的重量最大,因为公共汽车/手推车受到交通的影响,并且无法保证等待转移可能花费的时间
【解决方案2】:

我将使用 A* Algorithm 描述我的解决方案,我认为这是 Dijkstra 算法的扩展(和改进——请不要开枪)更容易直观理解。它的基本原理是这样的:

  1. 将起始路径添加到优先级队列中,权重为距离到目前为止 + 到目标的最小距离
  2. 每次迭代,采用权重最低的路径并将其分解为距它一步之遥的每条路径(丢弃环绕自身的路径)并将其放回队列中。如果您找到一条以目标为终点的路径,请停止。

您可以使用两个权重:Stops 和 Distance/Time,而不是让您的权重简单地是距离到目前为止 + 到目标的最小距离,以这种方式进行比较:

基本上,比较:

  • 首先比较停靠点,并在可能的情况下报告此比较(即,如果它们不相同)
  • 如果停靠点相同,则比较行驶距离

并以这种方式对您的队列进行排序。

如果您曾经玩过Mario Party,请将止损视为星星,将距离视为硬币。在游戏的中间,一个有两颗星和十个硬币的人将在一个有一颗星和五十个硬币的人之上。

这样做可以保证您从优先级队列中取出的第一个节点将是可能停止数量最少的级别。

【讨论】:

    【解决方案3】:

    您的想法是正确的,但您实际上并不需要凭经验找到转移权重 - 您只需确保单次转移的重量大于最长可能旅行时间的重量。如果您给予的接送重量相当于一年的旅行时间,您应该是相当安全的。

    【讨论】:

      【解决方案4】:

      正如 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。将选择第一个解决方案。

      【讨论】:

      • 如果它们在同一行,为什么要在重量(A,B)上加 10000?我认为重点是在从 A(第 1 行)到 A(第 2 行)的转移中添加 10000。
      • @Alisa 想法相同,只是细节不同。我扩展了答案以显示它是如何工作的。
      【解决方案5】:

      我和你有同样的问题,直到现在。我正在使用 Dijkstra。转移处罚确实是一个非常好的主意,我已经使用了一段时间了。主要问题是您不能直接在重量中使用它,因为您首先必须识别转移。而且我不想修改算法。

      所以我一直在做的是,每次你找到一个转移,删除节点,添加惩罚权重并重新运行图表。

      但是这样我发现 Dijkstra 不起作用。这就是我尝试 Floyd-Warshall 的地方,它与 Dijkstra 相反,比较了每对顶点之间通过图形的所有可能路径。

      它帮助我解决了切换到 Floyd-Warshall 的问题。希望它也能帮助你。 它更容易编码,更容易实现。

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-18
      • 1970-01-01
      相关资源
      最近更新 更多