【问题标题】:dynamic programming : traversal of cities动态规划:城市遍历
【发布时间】:2012-11-17 21:38:53
【问题描述】:

我遇到了这个问题:

有两个人。有n个城市的有序序列,每对城市之间的距离是给定的。您必须将城市划分为两个子序列(不一定是连续的),使得 A 人访问第一个子序列中的所有城市(按顺序),人 B 访问第二个子序列中的所有城市(按顺序),并且使得A 和 B 的总距离最小化。假设 A 人和 B 人最初从各自子序列中的第一个城市开始。

我寻找它的答案,答案是:
令 c[i,j] 为第一个人停在城市 i 和第二个人停在城市 j 的最短距离。假设 i

c[0,j]= k 从 1 到 j-1 的 (d[k,k+1]) 之和
c[i,j] = min(c[k,j]+ d[k,i]) 如果 i!=0 其中 0

解决方法也可以看问题10here

现在,我的问题是:
1. 这个解没有定义 i=1(因为 k 没有值)。
2. 现在,假设我们正在寻找 c[2,3]。它将是 c[1,3]+ d[1,2]。现在 c[1,3] 表示人 B 访问了 0、2 和 3,而 A 人留在 1 或 B 访问了 2 和 3 和 A 访问了 0 和 1。此外,c[2,3] 表示 A 仅访问了 2/ 0,1,2 /0,2 /1,2。所以,

 c[1,3] = min(d[0,1]+ d[2,3], d[0,2]+ d[2,3])
 c[2,3] = min(d[0,1]+ d[1,2], d[0,2]+ d[1,3], d[1,2]+d[0,3], d[0,1]+d[1,3])

可以看出,解决方案没有重叠。

换句话说,2 已经被 c[1,3] 中的 B 覆盖了。因此,如果我们在 c[2,3] 中包含 c[1,3],则意味着 A 和 B 都访问了 2,这不是必需的,因为它只会增加成本。

如果我错了,请纠正我。

【问题讨论】:

  • 这不等于一个旅行者从旅行者B的终点开始,通过“第一个”到达A终点的所有城市吗?
  • @jdv-JandeVaan 你可能会这样看,如果你认为路径在那个“via”边缘被分割,这意味着那个边缘被移除了
  • 另一种观点:让“状态”是哪个人在哪个城市,给你一个二次节点数。您可以通过让 A 或 B 移动到下一个未访问的城市来从一个节点移动到下一个节点,即每个节点最多有两条边,所以边的二次数。最短路径(由 DP 计算,即 DAG-Shortest-Path)以二次(而非三次)时间给出解。

标签: algorithm dynamic-programming


【解决方案1】:

Q:: 城市序列的两人遍历:给定 n 个城市的有序序列,以及每对城市之间的距离。设计一种算法,将城市划分为两个子序列(不一定是连续的),使得 A 访问第一个子序列中的所有城市(按顺序),B 访问第二个子序列中的所有城市(按顺序),并且A 和 B 的总距离最小化。假设 A 人和 B 人最初从各自子序列中的第一个城市开始。

这是我对解决方案的理解::

假设城市是从 1 到 n 的数字。我们在 C(i, j) 上递归,如果人 A 在城市 i 结束并且人 B 在城市 j 结束,则行进的最小距离。不失一般性假设 i

令 C(0, n) 表示人 A 没有访问任何城市,而人 B 访问了 [1, n] 中的所有城市。

因此,C(0, j) = d(1,2) + d(2,3) + .... + d(j-1, j) (B 从城市 1 开始,按顺序直到城市 j)。

C(i, j),其中 i 不为 0 = 以下两种情况的最小值:

案例 1:A 人在城市 i 开始和停止。在这种情况下,C(i, j) = 人 B 行进的距离,按顺序从 1 到 j 到所有城市,跳过城市 i = d(1,2) + d(2,3) + ... + d(i-1, i+1) + d(i+1, i+2) + ... + d(j-1, j)

案例 2:人 A 在 i 之前从某个城市开始,因此有一个城市 k,他在去城市 i 之前旅行(他遍历的倒数第二个城市)。在这种情况下,C(i, j) = minimum {C(k, j) + d(k, i)} 其中 k 可以从 1 变化到 i-1。

问题的解决方案是最小值 { C(i,n) },其中 i 从 0 变化到 n-1。

我们可以按行主要顺序填充 DP 矩阵,因为 C(i,j) 的每次计算都需要距离 d 或 C(k,j),其中 k

算法的运行时间将是 O(n^3),因为有 O(n^2) 个条目需要我们进行计算,每个计算需要 O(n) 时间。

编辑 :: 我认为讲义中给出的解决方案缺少 case1。

【讨论】:

    【解决方案2】:

    您说得对,建议的解决方案有些混乱和不正确。

    思考问题的方式一如既往地归纳:如果我需要解决大小为 n 的问题,我该如何将其简化为更小的问题(0,...,n-1)。如果您想解决大小 n 的问题,请注意其中一名玩家需要将节点 n 带入他们的路径。

    C[i, j] 函数是一个辅助函数,表示如您所描述的“A 在 i 处停止,B 在 j 处停止的最小成本”。

    为了到达状态 C[i,j],玩家 B 必须从 j-1 到 j,当然除非 j-1 = i。在 j-1 = i 的情况下,j 必须来自某个 k

    C[i,j] = {
       C[i,j-1] + d[j-1,j]                   (if i < j-1)
       min C[k,i] + d[k,j] for 0 <= k < i    (if i = j-1)
    }
    

    使用此设置,您的基本情况就是 C[0, 1] = d[0,1]。

    那么你的最终答案是 min C[k, n] for 0

    【讨论】:

    • @dejan...您是对的,但我认为您的基本情况不正确...C[0,1]=0,因为 A 为 0,B 为 1(给定城市应该分为两个子序列,一个不需要遍历另一个序列的城市。所以,B不需要从0开始)
    • @Dejan 我认为有问题。假设最佳解决方案是 A 从 1 个城市旅行到 m 个城市,B 从 m+1 个城市旅行到 n 个城市,那么您的解决方案是否找到它。当你到达第二种情况(i = j-1)时,问题是你强迫B从i以下的某个地方来,而它不需要——j可能是B旅行的起点。我认为您可以通过在开头添加一个与任何其他城市的距离为零的幽灵/僵尸城市 0 来解决此问题,并定义基本情况 C(0,1) = d(0,1) = 0。请告诉我如果你认为我是对的。
    猜你喜欢
    • 2018-04-09
    • 1970-01-01
    • 2019-08-04
    • 2015-06-09
    • 2021-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多