【问题标题】:How should I generate the partitions / pairs for the Chinese Postman problem?我应该如何为中国邮递员问题生成分区/对?
【发布时间】:2010-04-26 17:44:55
【问题描述】:

我正在编写一个涉及解决Chinese Postman problem 的课程程序。我们的任务只需要我们编写一个程序来解决一个硬编码图,但我正在尝试自己解决一般情况。

给我带来麻烦的部分是为奇数顶点生成配对分区。

例如,如果我在图中有以下标记为奇数的顶点:

1 2 3 4 5 6

我需要找到我可以用这些顶点进行的所有可能的配对/分区。

我想我会得到i 分区:

  n = num of odd verticies  
  k = n / 2  
  i = ((2k)(2k-1)(2k-2)...(k+1))/2^n

因此,鉴于上面的 6 个奇数顶点,我们将知道我们需要生成 i = 15 分区。

这 15 个部分看起来像:

1 2   3 4   5 6
1 2   3 5   4 6
1 2   3 6   4 5
...
1 6   ...

然后,对于每个分区,我取每一对并找到它们之间的最短距离,然后为该分区求和。选择其对之间总距离最小的分区,然后我将奇数顶点之间的最短路径之间的所有边加倍(在所选分区中找到)。

这些代表邮递员必须走两次的边缘。

起初我以为我已经制定了一个合适的算法来生成这些分区:

  1. 从所有奇数顶点开始,按升序排序

    12 34 56

  2. 选择当前具有最大顶点的pair后面的pair

    12 [34] 56

  3. 将这对中的第二个数字加 1。将所有内容留给 所选对的左侧相同, 让一切都在右边 选定的对 剩余的 集合中的数字,按 递增顺序。

    12 35 46

  4. 重复

但是,这是有缺陷的。例如,我意识到当我到达末尾并且选择对位于最左边的位置(即)时:

[16] .. ..

我制定的算法将在这种情况下停止,并且不会生成以 [16] 开头的其余对,因为它的左侧没有可更改的对。

所以,它又回到了绘图板上。

以前研究过这个问题的人有任何提示可以帮助我指出生成这些分区的正确方向吗?

【问题讨论】:

  • 张贴你的(不)合适的算法进行批评......
  • @KevinDTimm,我已经编辑了我的问题以包含我有缺陷的生成算法。
  • 在发布了下面的递归算法之后,我想到了迭代算法——它类似于我为“惰性生成排列”(stackoverflow.com/questions/352203/353248#353248) 解释的算法,但并不那么简单。 (沿着每一对的 second 元素走,直到你看到一个下降,然后用它右边的 all 个中最小的更大的数字替换它,然后对剩余的元素进行排序.) 你最好使用递归。

标签: algorithm chinese-postman


【解决方案1】:

您可以使用递归算法构造分区。

取最低的节点,在本例中为节点 1。它必须与其他未配对的节点之一(2 到 6)配对。对于这些节点中的每一个,使用匹配 1 创建,然后对剩余的四个元素使用相同的算法找到剩余 4 个元素的所有对。

在 Python 中:

def get_pairs(s):
    if not s: yield []
    else:
        i = min(s)
        for j in s - set([i]):
           for r in get_pairs(s - set([i, j])):
               yield [(i, j)] + r

for x in get_pairs(set([1,2,3,4,5,6])):
    print x

这会生成以下解决方案:

[(1, 2), (3, 4), (5, 6)]
[(1, 2), (3, 5), (4, 6)]
[(1, 2), (3, 6), (4, 5)]
[(1, 3), (2, 4), (5, 6)]
[(1, 3), (2, 5), (4, 6)]
[(1, 3), (2, 6), (4, 5)]
[(1, 4), (2, 3), (5, 6)]
[(1, 4), (2, 5), (3, 6)]
[(1, 4), (2, 6), (3, 5)]
[(1, 5), (2, 3), (4, 6)]
[(1, 5), (2, 4), (3, 6)]
[(1, 5), (2, 6), (3, 4)]
[(1, 6), (2, 3), (4, 5)]
[(1, 6), (2, 4), (3, 5)]
[(1, 6), (2, 5), (3, 4)]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-04-18
    • 1970-01-01
    • 2023-01-20
    • 2020-05-23
    • 2017-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多