【问题标题】:Traveling Salesman: Get all possible Paths with recursion旅行推销员:通过递归获取所有可能的路径
【发布时间】:2016-08-17 08:00:21
【问题描述】:

我正在尝试编写一个递归方法来计算旅行商问题的所有可能路径:

def allPaths(toCover, path=""):

    path = path + toCover[0]
    toCover.remove(toCover[0])

    if len(toCover)>0:
        for x in range (0, len(toCover)):
            #swop cities
            temp = toCover[0]
            toCover[0] = toCover[x]
            toCover[x] = temp
            allPaths(toCover, path)
    else :
        print path


cities = ["A", "B", "C", "D"]

allPaths(cities)

所以,我有一个城市列表。

我将列表中的第一个城市添加到当前路径。 我从城市toCover 列表中删除了添加的城市。 对于列表中剩余的每个城市,我再次调用allPaths() 函数。我修改了列表参数,每个城市都在索引 0 上一次。

(我想用以下列表实例调用 allPaths:

[B,C,D]
[C,B,D]
[D,C,B]

)

但是,当我对此进行调试时,city-toCover 列表会在 allPaths 的所有“实例”中进行修改。这意味着,它返回第一个有效路径“ABCD”,但随后不会继续,因为对于下一次调用,所有城市都已被删除。

我做错了什么?

我希望这个解释有点清楚......

【问题讨论】:

  • 找出细节是一个有趣的练习——但如果你想要的只是一个解决方案,itertools 已经内置了排列。

标签: python recursion traveling-salesman


【解决方案1】:

解决方法很简单。这是因为toCover(如果你问我,应该命名为to_cover,但是嘿,这是你的代码^^)是一个列表。 列表是可变的,这意味着每个实例都持有对原始对象的引用,从而导致所有更改都在所有引用上完成的问题(好吧,它们实际上只是对对象完成,但是引用指向该对象,所以...)。

你可以通过三种方式解决:

  • 使用元组代替,或者只是像使用元组一样使用列表

    您将cities = ["A", "B", "C", "D"] 替换为cities = ("A", "B", "C", "D")(如果您想要一个元组),并使用toCover = toCover[1:] 而不是toCover.remove(toCover[0]),这应该是(如果它应该修改底层对象) del toCover[0] 反正。

    x[1:] 创建一个列表或元组的切片(尽管您可以在自己的类型中为该运算符实现几乎任何东西),从而产生一个新实例,该实例具有除第一个元素之外的任何元素。见here(python 文档缺乏真正的解释,不要问我为什么)。

  • 一遍又一遍地复制列表

    这个解决方案是解决问题的常用方法,但它确实不是这里的方法。这可以通过复制这样的列表来绕过引用:toCover = toCover[:](这应该在函数的顶部)。它创建一个包含整个列表的切片(同样:this link),有效地复制它。

  • 使用itertools.permutations 可以做你想做的事。 (请参阅@John Coleman 对您的问题的评论)有关详细信息,请参阅python documentation

希望能帮到你

代号Lambda

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-06-22
    • 1970-01-01
    • 2011-09-08
    • 2015-09-03
    • 1970-01-01
    • 2015-04-28
    • 2011-12-07
    • 1970-01-01
    相关资源
    最近更新 更多