【问题标题】:Need help to modify flood fill algorithm需要帮助修改洪水填充算法
【发布时间】:2016-01-26 03:03:21
【问题描述】:

我正在尝试修改填充算法以返回最终的 2D 矩阵,其中所有 color1 仅用 color2 着色。泛洪应该从矩阵中的 x, y 开始。

测试用例 1:

之前:

matrix = [[4, 3, 1, 2],
          [3, 1, 1, 2],
          [1, 2, 4, 5]]

matrix = fill(matrix, x = 0, y = 2, color1 = 1, color2 = 2)之后

matrix = [[4, 3, 2, 2],
          [3, 2, 2, 2],
          [1, 2, 4, 5]]

测试用例 2:

之前:

matrix = [[3, 2, 4],
          [5, 1, 4],
          [4, 3, 1]]

matrix = fill(matrix, x = 0, y = 0, color1 = 3, color2 = 1)之后

matrix = [[1, 2, 4],
          [5, 1, 4],
          [4, 3, 1]]

测试用例 3:

之前:

matrix = [[2, 1, 1],
          [2, 1, 2],
          [2, 2, 2]]

matrix = fill(matrix, x = 1, y = 2, color1 = 2, color2 = 1)之后

matrix = [[1, 1, 1],
          [1, 1, 1],
          [1, 1, 1]]

这非常类似于我在Invent with Python Blog 发现的僵尸感染问题

目前,我有只修改全局矩阵的算法。

def fill(matrix, x, y, color1, color2):

    matWidth = len(matrix)
    matHeight = len(matrix[0])
    if x < 0 or y < 0 or x >= matWidth or y >= matHeight:
        return  

    if matrix[x][y] == color2 or matrix[x][y] != color1:
        return
    if matrix[x][y] == color1:
        matrix[x][y] = color2

    fill(matrix, x - 1, y, color1, color2)
    fill(matrix, x + 1, y, color1, color2)
    fill(matrix, x, y - 1, color1, color2)
    fill(matrix, x, y + 1, color1, color2)

有没有办法修改 fill() 使其接受矩阵作为参数并返回最终的填充矩阵?

非常感谢!

我非常接近解决这个问题。这是我的解决方案:

def fill(matrix, x, y, color1, color2):
    matWidth = len(matrix)
    matHeight = len(matrix[0])

    if x < 0 or y < 0 or x >= matWidth or y >= matHeight:
        return matrix  

    if mat[x][y] != color1:
        return matrix

    else:
        matrix[x][y] = color2
    if x == 0:
        if y == 0:
            if matrix[x + 1][y] == color1 and color[x + 1][y] != color2:
                matrix = fill(matrix, x + 1, y, color1, color2)
            if matrix[x][y + 1] == color1 and matrix[x][y + 1] != color2:
                matrix = fill(matrix, x, y + 1, color1, color2)
        if y == matHeight - 1:
            if matrix[x][y - 1] == color1 and matrix[x][y - 1] != color2:
                matrix = fill(matrix, x, y - 1, color1, color2)
            if matrix[x + 1][y] == color1 and matrix[x + 1][y] != color2:
                matrix = fill(matrix, x + 1, y, color1, color2)
        else:
            if matrix[x][y - 1] == color1 and matrix[x][y - 1] != color2:
                matrix = fill(matrix, x, y - 1, color1, color2)
            if matrix[x][y + 1] == color1 and matrix[x][y + 1] != color2:
                matrix = fill(matrix, x, y + 1, color1, color2)
            if matrix[x + 1][y] == color1 and matrix[x + 1][y] != color2:
                matrix = fill(matrix, x + 1, y, color1, color2)
    if x == matWidth - 1:
        if y == 0:
            if matrix[x - 1][y] == color1 and matrix[x - 1][y] != color2:
                matrix = fill(matrix, x - 1, y, color1, color2)
            if matrix[x][y + 1] == color1 and matrix[x][y + 1] != color2:
                matrix = fill(matrix, x, y + 1, color1, color2)
        if y == matHeight - 1:
            if matrix[x][y - 1] == color1 and matrix[x][y - 1] != color2:
                matrix = fill(matrix, x, y - 1, color1, color2)
            if matrix[x - 1][y] == color1 and matrix[x - 1][y] != color2:
                matrix = fill(matrix, x - 1, y, color1, color2)
        else:
            if matrix[x][y - 1] == color1 and matrix[x][y - 1] != color2:
                matrix = fill(matrix, x, y - 1, color1, color2)
            if matrix[x][y + 1] == color1 and matrix[x][y + 1] != color2:
                matrix = fill(matrix, x, y + 1, color1, color2)
            if matrix[x - 1][y] == color1 and matrix[x - 1][y] != color2:
                matrix = fill(matrix, x - 1, y, color1, color2)

    if y > 0 and matrix[x][y-1] == color1 and matrix[x][y-1] != color2:
        matrix = fill(matrix, x, y-1, color1, color2)

    if y < matHeight and matrix[x][y+1] == color1 and matrix[x][y+1] != color2:
        matrix = fill(matrix, x, y-1, color1, color2)

    if x < matWidth and matrix[x+1][y] == color1 and matrix[x+1][y] != color2:
        matrix = fill(matrix, x+1, y, color1, color2)

    if x > 0 and matrix[x-1][y] == color1 and matrix[x-1][y] != color2:
        matrix = fill(matrix, x-1, y, color1, color2)

    return matrix

任何帮助将不胜感激。谢谢

【问题讨论】:

  • 您需要一份矩阵副本,阅读docs.python.org/2/library/copy.html
  • 你为什么要递归地这样做,它的效率极低。只需使用嵌套的for 循环来访问矩阵的所有单元格并将任何颜色1 替换为颜色2。如果矩阵是函数的参数,它将更改其中的值,因此实际上不需要返回它(但如果你愿意,你可以这样做)。
  • @martineau 感谢您的回复。我会进行编辑。问题指出 x, y 是泛滥的起始位置。这样,我们就不能使用嵌套循环。 ://
  • @ishaan 我阅读了文档,我想我不明白如何使用 deepcopy 解决它。
  • 我不明白。你为什么不在最后和你返回的其他地方做return matrix

标签: python recursion flood-fill


【解决方案1】:

简单地返回矩阵:

def fill(matrix, x, y, color1, color2):

    matWidth = len(matrix)
    matHeight = len(matrix[0])
    if x < 0 or y < 0 or x >= matWidth or y >= matHeight:
        return matrix

    if matrix[x][y] == color2 or matrix[x][y] != color1:
        return matrix
    if matrix[x][y] == color1:
        matrix[x][y] = color2

    fill(matrix, x - 1, y, color1, color2)
    fill(matrix, x + 1, y, color1, color2)
    fill(matrix, x, y - 1, color1, color2)
    fill(matrix, x, y + 1, color1, color2)

    return matrix

或者如果您不喜欢总是返回它,请使用包装器在最后只返回一次:

def fill(matrix, x, y, color1, color2):
    def fill(matrix, x, y, color1, color2):

        matWidth = len(matrix)
        matHeight = len(matrix[0])
        if x < 0 or y < 0 or x >= matWidth or y >= matHeight:
            return  

        if matrix[x][y] == color2 or matrix[x][y] != color1:
            return
        if matrix[x][y] == color1:
            matrix[x][y] = color2

        fill(matrix, x - 1, y, color1, color2)
        fill(matrix, x + 1, y, color1, color2)
        fill(matrix, x, y - 1, color1, color2)
        fill(matrix, x, y + 1, color1, color2)
    fill(matrix, x, y, color1, color2)
    return matrix

在这种情况下,您也可以去掉大多数参数。这是我这样做的一个版本,也使代码更简单:

def fill(matrix, x, y, color1, color2):
    def fill(x, y):
        if 0 <= x < matWidth and 0 <= y < matHeight and matrix[x][y] == color1:
            matrix[x][y] = color2
            fill(x - 1, y)
            fill(x + 1, y)
            fill(x, y - 1)
            fill(x, y + 1)
    matWidth = len(matrix)
    matHeight = len(matrix[0])
    fill(x, y)
    return matrix

【讨论】:

  • 非常感谢!奇迹般有效。想支持答案,但我没有足够的声誉。 ://
  • 就地修改矩阵返回它几乎总是一个坏主意。您需要选择其中一个并保持一致。如果需要,请复制一份:matrix = matrix[:]
  • 我不知道函数可以充当包装器。太棒了!
  • @MarkRansom “你需要选择一个或另一个” 不,我没有。我同意“应该”,但不同意“需要”。
  • @StefanPochmann 这是编程错误的来源。我会坚持我的强语,谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-19
  • 2014-02-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多