简体   繁体   English

通过连接的节点查找最长的非重复路径

[英]Finding longest non-repeating path through connected nodes

I've been working on this for a couple of days now without success. 我已经为此工作了几天,但没有成功。 Basically, I have a bunch of nodes arranged in a 2D matrix. 基本上,我有一堆节点以2D矩阵排列。 Every node has four neighbors, except for the nodes on the sides and corners of the matrix, which have 3 and 2 neighbors, respectively. 每个节点都有四个邻居,除了矩阵的边和角上的节点分别有3个和2个邻居。 Imagine a bunch of square cards laid out side by side in a rectangular area--the project is actually simulating a sort of card/board game. 想象一下在矩形区域中并排放置的一堆正方形纸牌-该项目实际上是在模拟一种纸牌/棋盘游戏。

Each node may or may not be connected to the nodes around it. 每个节点可能会或可能不会连接到它周围的节点。 Each node has a function (get_connections()), that returns the nodes immediately around it that it is connected to (so anywhere from 0 to 4 nodes are returned). 每个节点都有一个函数(get_connections()),该函数将立即返回与其连接的节点(因此将返回0至4个节点)。 Each node also has an "index" property, that contains it's position on the board matrix (eg '1, 4' -> row 1, col 4). 每个节点还具有“索引”属性,其中包含其在电路板矩阵上的位置(例如“ 1,4”->第1行,第4行)。 What I am trying to do is find the longest non-repeating path of connected nodes given a particular "start" node. 我要尝试做的是找到给定特定“开始”节点的连接节点的最长非重复路径。

I've uploaded a couple of images that should give a good idea of what I'm trying to do: 我上传了几张图片,这些图片应该可以很好地说明我要执行的操作:

www.necessarygames.com/junk/10-days-problem-01.jpg
(source: necessarygames.com ) (来源: essentialgames.com

www.necessarygames.com/junk/10-days-problem-02.jpg
(source: necessarygames.com ) (来源: essentialgames.com

In both images, the highlighted red cards are supposedly the longest path of connected cards containing the most upper-left card. 在两个图像中,突出显示的红牌应该是包含最左上角牌的已连接牌的最长路径。 However, you can see in both images that a couple of cards that should be in the path have been left out (Romania and Maldova in the first image, Greece and Turkey in the second) 但是,您都可以在两个图像中看到应该去的路径中的几张纸牌已被忽略(第一幅图像中为罗马尼亚和马尔多瓦,第二幅图像中为希腊和土耳其)

Here's the recursive function that I am using currently to find the longest path, given a starting node/card: 给定起始节点/卡,这是我当前正在使用的递归函数,用于查找最长路径:

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

The problem here has to do with the processed_countries list: if you look at my first screenshot, you can see that what has happened is that when Ukraine came around, it looked at its two possible choices for longest path (Maldova-Romania, or Turkey, Bulgaria), saw that they were both equal, and chose one indiscriminantly. 这里的问题与处理国家列表有关:如果查看我的第一个屏幕截图,您会看到发生的事情是当乌克兰走近时,它查看了最长路径的两个可能选择(马尔代夫-罗马尼亚或土耳其) ,保加利亚),看到他们都是平等的,便毫不犹豫地选择了一个。 Now when Hungary comes around, it can't attempt to make a path through Romania (where the longest path would actually be), because Romania has been added to the processed_countries list by Ukraine. 现在匈牙利来了,它不能尝试通过罗马尼亚(实际上是最长的路径)建立一条道路,因为罗马尼亚已经被乌克兰添加到了处理国家列表中。

Any help on this is EXTREMELY appreciated. 非常感谢您的帮助。 If you can find me a solution to this, recursive or not, I'd be happy to donate some $$ to you. 如果您能找到我的解决方案(递归与否),我很乐意向您捐款。

I've uploaded my full source code (Python 2.6, Pygame 1.9 required) to: 我已将完整的源代码(需要Python 2.6,Pygame 1.9)上传到:

http://www.necessarygames.com/junk/planes_trains.zip http://www.necessarygames.com/junk/planes_trains.zip

The relevant code is in src/main.py, which is all set to run. 相关代码位于src / main.py中,所有代码均已设置为可以运行。

您知道循环图中的最长路径问题是NP难的吗?

...Romania has been added to the processed_countries list by Ukraine. ...罗马尼亚已被罗马尼亚添加到处理国家列表中。

Use separate processed_countries lists for each graph path. 为每个图形路径使用单独的processed_countries列表。 They say one code example is worth thousand words, so I've changed your code a little (untested): 他们说一个代码示例值一千个单词,所以我对您的代码做了一些改动(未经测试):

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

Unrelated matters: 不相关的事项:

Traceback (most recent call last):
  File "main.py", line 1171, in <module>
    main()
  File "main.py", line 1162, in main
    interface = Interface(continent, screen, ev_manager)    
  File "main.py", line 72, in __init__
    self.deck = Deck(ev_manager, continent)
  File "main.py", line 125, in __init__
    self.rebuild(continent)  
  File "main.py", line 148, in rebuild
    self.stack.append(CountryCard(country, self.ev_manager))
  File "main.py", line 1093, in __init__
    Card.__init__(self, COUNTRY, country.name, country.image, country.color, ev_manager)  
  File "main.py", line 693, in __init__
    self.set_text(text)
  File "main.py", line 721, in set_text
    self.rendered_text = self.render_text_rec(text)  
  File "main.py", line 817, in render_text_rec
    return render_textrect(text, self.font, text_rect, self.text_color, self.text_bgcolor, 1)       
  File "/home/vasi/Desktop/Planes and Trains/src/textrect.py", line 47, in render_textrect
    raise TextRectException, "The word " + word + " is too long to fit in the rect passed."
textrect.TextRectException: The word Montenegro is too long to fit in the rect passed.

There are 16 different bak files in your source package. 您的源程序包中有16个不同的bak文件。 Sixteen. 十六。 Sixteeeen. Sixteeeen。 Think about it and start to use version control. 考虑一下并开始使用版本控制。

Brute force method: 蛮力法:

  1. Create a depth first connected list. 创建一个深度优先的连接列表。 Store List L and its Length T. 商店清单L及其长度T。

  2. For each connection of this list: 对于此列表的每个连接:

    • Push Whole Diagram 推整个图
    • Delete connection. 删除连接。
    • Create a depth first connected list. 创建一个深度优先的连接列表。
    • If list is longer than T: set T to length and list to L then recursive call 2. 如果list的长度大于T:将T设置为length并将list设置为L,则递归调用2。
    • Pop Whole Diagram. 流行整个图。
    • return 返回

This should create a flood fill style solution of all the possible ways of connecting these nodes. 这应该为连接这些节点的所有可能方式创建一种洪水填充样式的解决方案。

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

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