繁体   English   中英

旅行推销员:通过递归获取所有可能的路径

[英]Traveling Salesman: Get all possible Paths with recursion

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

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]

)

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

我究竟做错了什么?

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

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

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

  • 改用元组,或者像使用元组一样使用列表

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

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

  • 一遍又一遍地复制列表

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

  • 使用itertools.permutations可以完成您想做的事情。 (请参阅@John Coleman 对您的问题的评论)有关更多详细信息,请参阅python 文档

我希望我能帮上忙

代号Lambda

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM