【问题标题】:Finding all combinations in a list with a constraint in python在python中查找具有约束的列表中的所有组合
【发布时间】:2015-04-03 13:29:55
【问题描述】:

我最近一直在尝试学习递归算法,但我遇到了死胡同。给定一定数量的列表,每个列表代表从一个商店到所有其他商店所需的时间,以及一个包含一系列时间间隔的列表,有没有办法使用递归找到商店之间所有可能的路线?

例如

list_of_shops = [shop1, shop2, shop3, shop4] 
# Index for this list and the one below are the same

list_of_time_it_takes = [[0, 2, 1, 4], [2, 0, 1, 4], [2, 1, 0, 4], [1, 2, 3, 0]]
# the 0 indicates the index of the shop. It takes 0 minutes to reach the shop from itself.

list_of_time_intervals = [0, 2, 2]

商店只能访问一次。我们可以看到以 2 分钟的间隔访问了 3 家商店,可能的路线是:

shop4 > shop2 > shop1

商店 3 > 商店 1 > 商店 2

所以我正在尝试使用以下代码通过所需的输出解决上述问题:

shops = [[0, 2, 1, 4, 9], [2, 0, 1, 4, 9], [2, 1, 0, 4, 9], [1, 2, 3, 0, 11], [3, 6, 16, 4, 0]]
times = [0, 2, 2, 4, 11]
list_of_shops = ['shop0', 'shop1', 'shop2', 'shop3', 'shop4']
index_dict = {}



def function(shops_input, times_input, i, index_list):

    #print("given i = ", i)
    #print("given shops = ", shops_input)
    #print("given times = ", times_input)

    shops_copy, times_copy = shops_input[:], times_input[:]
    pop = times_copy.pop(0)
    #print("obtained pop = ", pop)
    if shops[i] in shops_copy:

        index_list.append(shops.index(shops[i]))
        shops_copy.pop(shops_copy.index(shops[i]))
        if len(index_list) == len(times):
            index_dict[list_of_shops[index_list[0]]] = index_list
            print(index_list)
            print(index_dict)
        if len(times_copy):
            try:
                function(shops_copy, times_copy, shops[i].index(times_copy[0]), index_list)
            except ValueError:
                return


def main_function(shops, times):
    for i in range(len(shops)):
        function(shops, times, i, [])
        print("---------end funct---------")


main_function(shops, times)

它在某些情况下有效,但绝对不是在所有情况下。它应该根据给定的时间间隔为我提供所有可能的路线,但是,它似乎在很多情况下都不起作用。

例如,如果我将商店和时间更改为:

shops = [[0,1,1,1],[1,0,1,1],[1,1,0,1],[1,1,1,0]]
times = [0, 1, 1]

它给出 2 种可能性的输出 -> 从 shop2 = [2,0,1] 和 -> 从 shop3 = [3,0,1] 开始。有什么方法可以让我的算法发挥作用吗?

【问题讨论】:

    标签: python algorithm recursion


    【解决方案1】:

    我写了一个小脚本来解决你的问题。首先让我们看看输出。它是一个表示树的字典。根本元素是将所有东西放在一起。鉴于您在该节点(或商店)上,所有其他子节点(或叶子)都是可能的访问。

    {'children': [{'children': [{'children': [{'children': [{'children': [{'children': [],
                                                                           'shop': 4}],
                                                             'shop': 3}],
                                               'shop': 0}],
                                 'shop': 1}],
                   'shop': 0},
                  {'children': [{'children': [{'children': [{'children': [{'children': [],
                                                                           'shop': 4}],
                                                             'shop': 3}],
                                               'shop': 1}],
                                 'shop': 0}],
                   'shop': 1},
                  {'children': [{'children': [{'children': [{'children': [{'children': [],
                                                                           'shop': 4}],
                                                             'shop': 3}],
                                               'shop': 1}],
                                 'shop': 0}],
                   'shop': 2},
                  {'children': [{'children': [{'children': [{'children': [{'children': [],
                                                                           'shop': 4}],
                                                             'shop': 3}],
                                               'shop': 0}],
                                 'shop': 1}],
                   'shop': 3},
                  {'children': [], 'shop': 4}],
     'shop': 'root'}
    Drink beer :)
    

    嗯,这是脚本。如果您有任何疑问,请询问:)

    shops = [[0,1,1,1],[1,0,1,1],[1,1,0,1],[1,1,1,0]]
    times = [0, 1, 1]
    
    """
    Data structure
    {
        shop: 'root',
        children: [
            {
                shop: 1,  # index of the shop
                children: [  # shops where you can go from here
                    {
                        shop: 2,
                        children: [...]
                    }, 
                    ...
                ]
            },
            ...
        ]
    }
    
    """
    
    def get_shop(index):
        return shops[index]
    
    
    def get_next_shop_indexes(shop, time_interval):
        next_shops = []
        for index, shop_time_interval in enumerate(shop):
            if shop_time_interval == time_interval:
                next_shops.append(index)
        return next_shops
    
    
    def build_route_branch(branch, shop_index, time_intervals):
        shop = get_shop(shop_index)
        next_shop_indexes = get_next_shop_indexes(shop, time_intervals[0])
        for next_shop_index in next_shop_indexes:
            child_branch = {
                'shop': next_shop_index,
                'children': []
            }
            branch['children'].append(child_branch)
            if len(time_intervals) > 1:
                child_branch = build_route_branch(
                    child_branch, 
                    next_shop_index, 
                    time_intervals[1:]
                )
    
    tree = {
        'shop': 'root',
        'children': []
    }
    for index, shop in enumerate(shops):
        branch = build_route_branch(tree, index, times)
    
    import pprint
    pprint.pprint(tree)
    
    print 'Drink beer :)'
    

    【讨论】:

    • 谢谢!我了解树结构的基础知识,但我从未使用过它们。有没有办法使用您提供的解决方案来获得我可以使用的可能路线的可重用表示?例如,一个字典将包含作为键的起点,并将作为键的值包含从该点开始的所有路线?我之所以问,是因为这是一个需要使用这些值的稍大项目的一部分。非常感谢!
    • 当然可以,您只需要获取该输出,并将其转换为您想要的。我会把这个挑战留给你 :)
    • 那我就上吧!顺便问一下,有没有一种简单的方法来设置它,使算法中没有重复?例如,如果我想排除 shop1 -> shop2 -> shop1 类型的路线。或者那样做是不是效率低下?
    • 你当然可以,但是你需要以不同的方式存储东西,这样你才能访问节点的“历史”。
    猜你喜欢
    • 2019-04-27
    • 2015-10-15
    • 2020-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-26
    • 1970-01-01
    相关资源
    最近更新 更多