寻找连接节点的最长非重复路径

70 阅读3分钟

我们有一组节点,它们排列在一个二维矩阵中。每个节点都有四个相邻节点,除了矩阵的边缘和角上的节点,它们分别有三个和两个相邻节点。想象一下,一堆方形卡片并排摆放在一个矩形区域中,该项目实际上模拟的是一种纸牌/棋盘游戏。

每个节点可能连接或不连接其周围的节点。每个节点都有一个函数 get_connections(),它返回该节点周围与之相连的节点(因此返回的节点数量从 0 到 4 不等)。每个节点还具有一个“索引”属性,其中包含其在棋盘矩阵上的位置(例如,“1, 4”-> 第 1 行,第 4 列)。我们尝试做的是找到给定特定“起始”节点的连接节点的最长非重复路径。

这里有一个我们正在尝试做的事情的几个示例图片:

示例图片 1

示例图片 2

在两张图片中,突出显示的红色卡片应该是包含最左上角卡片的最长的已连接卡片路径。然而,您可以在两张图片中看到,一些应该在路径中的卡片被遗漏了(第一张图片中的罗马尼亚和摩尔多瓦,第二张图片中的希腊和土耳其)。

以下是我们目前用来查找给定起始节点/卡片的最长路径的递归函数:

def get_longest_trip(self, board, processed_connections = list(), 
                     processed_countries = list()):
    #Append this country to the processed countries list,
    #so we don't re-double over it
    processed_countries.append(self)
    possible_trips = dict()
    if self.get_connections(board):
        for i, card in enumerate(self.get_connections(board)):
            if card not in processed_countries:
                processed_connections.append((self, card))
                possible_trips[i] = card.get_longest_trip(board, 
                                                          processed_connections, 
                                                          processed_countries)
        if possible_trips:       
            longest_trip = []
            for i, trip in possible_trips.iteritems(): 
                trip_length = len(trip)
                if trip_length > len(longest_trip):
                    longest_trip = trip
            longest_trip.append(self)         
            return longest_trip
        else:
            print
            card_list = []
            card_list.append(self)
            return card_list
    else:
        #If no connections from start_card, just return the start card 
        #as the longest trip
        card_list = []
        card_list.append(board.start_card)
        return card_list

这里的问题与 processed_countries 列表有关:如果您查看我的第一张屏幕截图,您会看到发生的事情是当乌克兰出现时,它查看了最长路径的两种可能选择(摩尔多瓦-罗马尼亚或土耳其、保加利亚),发现它们相等,并随意选择了一个。现在,当匈牙利出现时,它无法尝试通过罗马尼亚(实际上最长路径所在的地方)建立路径,因为罗马尼亚已被乌克兰添加到 processed_countries 列表中。

2、解决方案

这种情况下,一种可能的解决方案是为每个图路径使用单独的 processed_countries 列表。以下是已修改的代码的一个示例:

def get_longest_trip(self, board, processed_countries = list()):
    # see https://stackoverflow.com/questions/576988/python-specific-antipatterns-and-bad-practices/577198#577198
    processed_countries = list(processed_countries)
    processed_countries.append(self)

    longest_trip = list()
    if self.get_connections(board):
        possible_trips = list()
        for card in self.get_connections(board):
            if card not in processed_countries:
                possible_trips.append(card.get_longest_trip(board, 
                                                            processed_countries))
        if possible_trips:
            longest_trip = max(possible_trips, key=len)
            longest_trip.append(self)

    if not longest_trip:
        longest_trip.append(self)
    return longest_trip

这种变化确保了每个图路径都有自己的 processed_countries 列表,从而避免了重复访问问题。通过这种修改,该函数现在应该能够找到给定特定起始节点的连接节点的最长非重复路径。