【问题标题】:Python find the largest square in the matrix dynamic programmingPython在矩阵动态规划中找到最大的正方形
【发布时间】:2020-12-24 15:23:49
【问题描述】:

我有一个矩阵如下(Python):

matrix = """
   ...o..o.o
   ...oo....
   ...o....o
   ..o.ooo..
   o...o....
   .oo......
   ..o....o.
   .oo......
   .........
"""

其中“o”是一个障碍,我需要在这个矩阵中找到最大的正方形。 并替换相应的“。”像下面的'x'

"""
   xxxo..o.o
   xxxoo....
   xxxo....o
   ..o.ooo..
   o...o....
   .ooxxxx..
   ..oxxxxo.
   .ooxxxx..
   ...xxxx..
""

在这里找到了类似的问题(SO),但没有任何帮助。

【问题讨论】:

  • 您可以建立一个包含编号的矩阵。连续点,那么测量会更容易。你能告诉我们你到目前为止得到了什么吗?
  • @DanielHao 第二部分,我的代码是否可行(上面的链接)?
  • 问题。不是——你又跑了吗?它显示错误...
  • @DanielHao 因为网站使用的是python 2.7,而我的代码是3及以上,我使用该网站只是为了托管我的代码,而不是运行。尝试在你的机器上运行代码

标签: python algorithm dynamic-programming


【解决方案1】:

正如我之前建议的那样,如果您可以建立一个正确的数据结构来首先包含所有连续点数,然后从那里开始工作,那么制定解决方案会更容易。以下是显示此内容的示例代码:(此处为第 1 部分答案,第 2 部分 - 留作练习)此代码取自另一个 S/O 帖子 (@AlainT),并相应地修改以适应此问题/格式。 (顺便说一句 - 您的代码示例根本不起作用,可能是格式问题?)

def bigSquare(matrix):
    spanSize = [ list(map(len,row.split("o"))) for row in matrix ]
    
    # print([s for ss in spanSize for s in ss if s>0]) # your array of numbers
    spans    = [ [c for s in ss
                    for c in range(s,-1,-1)]
                 for ss in spanSize
                ]
    
    #print(f' spans: {spans} ')
    
    result   = (0,0,0,0,0) # area, height, width, top, left
    
    for r,row in enumerate(spans):
        for c in range(len(row)):
            nextSpans = accumulate( (spanRow[c] for spanRow in spans[r:]),min)
            rectSize  = max( [(w*h,h,w) for h,w in enumerate(nextSpans,1)] )
            print(r, c, rectSize)
            
            result    = max(result,rectSize+(r,c))
    return result[0]   # return the Square Area


if __name__ == '__main__':
    matrix =['...o..o.o',
             '...oo....',
             '...o....o',
             '..o.ooo..',
             'o...o....',
             '.oo......',  # <--- start
             '..o....o.',
             '.oo......',
             '.........']
   
    print(bigSquare(matrix))   # Output: 16 

【讨论】:

    【解决方案2】:

    可以使用动态编程以O(n²) 的复杂度来完成。这个想法是,只有当上、左和左上的正方形具有相同的尺寸时,你才有一个更大的正方形。否则,当前单元格的最大平方只是上面考虑的正方形中最小的正方形,增加了 1。 代码如下:

    matrix = """
       ...o..o.o
       ...oo....
       ...o....o
       ..o.ooo..
       o........
       .oo......
       ..o....o.
       .oo......
       .........
    """
    
    matrix = [list(r) for r in matrix.split()]
            
    dp = [[0] * len(matrix) for _ in range(len(matrix))]
    # max_square_dim, row, column
    max_squares = [(0, None, None)]
    
    for ri, r in enumerate(matrix):
        for ci, c in enumerate(r):
            dp[ri][ci] = 0 if c == 'o' \
                else (1 if ri == 0 or ci == 0 
                else min(dp[ri - 1][ci], dp[ri][ci - 1], dp[ri - 1][ci - 1]) + 1)
            
            max_squares = [(dp[ri][ci], ri, ci)] if dp[ri][ci] > max_squares[0][0] \
                else (max_squares + [(dp[ri][ci], ri, ci)] if dp[ri][ci] == max_squares[0][0]
                else max_squares)
                
    
    for max_square in max_squares:
        for r in matrix[max_square[1] - max_square[0] + 1:max_square[1] + 1]:
            r[max_square[2] - max_square[0] + 1:max_square[2] + 1] = ['x'] * max_square[0]
          
    result = '\n'.join([''.join(r) for r in matrix])
            
    print(result)
    

    最后,当您必须用所有xs 替换最大的正方形时,您只需检索最大正方形的右下角顶点的索引(存储在max_square 中)并进行列表替换。


    编辑:如果你有多个最大的正方形,而不是声明一个max_square,你有一个它们的列表(在更新代码中我将它重命名为max_squares)。然后,每次遇到与最大尺寸相同的正方形时,只需将其附加到max_squares。但是,请考虑重叠正方形的可能性。

    【讨论】:

    • 谢谢,但是如果我有多个(大)相同大小的正方形会发生什么?,我可以根据它的位置(顶部,底部)等分别突出显示吗?
    • 没想过多个方块,看编辑和新代码。
    • 太棒了!不过最后一个问题,如果我想选择两个正方形之间的(左上角)正方形,那么我应该选择max_squares[0] 对吗?
    • 没错,矩阵是从顶部逐行访问,从左侧逐列访问。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-28
    • 2011-02-06
    • 2023-03-06
    • 2015-04-29
    • 1970-01-01
    • 1970-01-01
    • 2017-02-20
    相关资源
    最近更新 更多