繁体   English   中英

Python中的地图颜色算法

[英]Map Color Algorithm in Python

我在Python(3.2版)中有一个2D数组,如下所示:

...AAA....
...AAABB..
..BBBBBCC.
.....CCCC.
.DDD..CC..
.DDD......

它代表一种地图,其区域涂有不同的颜色。 上面的示例显示了四个不同的区域A,B,C和D。

这是为数组建立索引的示例:map [1] [5] =='A'将返回True。

我正在尝试编写一个函数,该函数接受这样的数组和行/列索引,并返回具有相同“颜色”的相邻空格的数量。 因此,使用上面的示例,这里有一些返回值(参数分别是数组,行和列号:

6 <-- countArea(map, 5, 2)
8 <-- countArea(map, 2, 8)

我想将其实现为递归函数,但我无法弄清楚。 这是我到目前为止的内容:

def countArea(map, row, col):

    key = map[row][col]

    if (map[row-1][col] == key):
        return 1 + countArea(map, row-1, col)
    elif (map[row+1][col] == key):
        return 1 + countArea(map, row+1, col)
    elif (map[row][col+1] == key):
        return 1 + countArea(map, row, col+1)
    elif (map[row][col-1] == key):
        return 1 + countArea(map, row, col-1)
    else:
        return 1

我知道我在这里缺少一些基本知识。 我基本上是说“这是当前字符,现在从各个方向看一下它是否具有相同的字符。”

我的问题是,在此递归定义中我缺少什么?

谢谢你的帮助。

我的问题是,在此递归定义中我缺少什么?

一旦对网格平方进行了计数,就不能再次对其进行计数(这包括通过对countArea()的递归调用进行计数!)

您当前的算法会尽可能向北移动,然后继续向南走一步,然后向北走一步。 重复执行此两步序列,直到堆栈空间用完。

如果愿意,您可以在Wikipedia上阅读有关此问题的算法。

在您的代码中,算法将在给定输入字段的左侧查找一个字段,而在递归调用中,算法将再次在初始字段上调用该函数。 (您显然不想要什么,因为它会导致无限递归)

方法1

在仍然使用递归的情况下克服此问题的一种方法是指定一个方向 ,在该方向上递归应查找更多相同类型的字段。 例如,对第一个字段正北(或上方 )的调用可能会递归地看起来更北或向东(或向右 ),向东的字段向南( 朝下 )和向东,依此类推。

通过明智地选择第一步,您可以确保在扫描区域中没有重叠。 但是,它需要一些调整以指定递归调用应扫描的方向。 但是:请注意,如果该区域悬空,则此算法将不起作用,因此,如果不能仅通过向右上方移动就可以到达起点东北方的每个字段。

存在更多类似这样的算法,它们也能够解决上述问题。 在Wikipedia上查看“ 洪水填充”

方法2

您还可以以某种方式保存已访问的字段,如果该字段已被访问,则可以直接从递归调用中返回。

以下实现应起作用:

def countArea(map, row, col, key=None, seen=None):
    if key is None:
        key = map[row][col]
    if seen is None:
        seen = set()
    seen.add((row, col))  # mark this location as visited
    n = 1
    for dy, dx in [(0, 1), (1, 0), (-1, 0), (0, -1)]:
         r, c = row + dy, col + dx
         if r < 0 or r >= len(map) or c < 0 or c >= len(map[0]):  # check boundaries
             continue
         # only increment and recurse if key matches and we haven't already visited
         if map[r][c] == key and (r, c) not in seen:
             n += countArea(map, r, c, key, seen)
    return n

例:

>>> print '\n'.join(''.join(row) for row in map)
...AAA....
...AAABB..
..BBBBBCC.
.....CCCC.
.DDD..CC..
.DDD......
>>> countArea(map, 5, 2)
6
>>> countArea(map, 2, 8)
8

请注意,这假设只将具有相同按键的区域仅在对角线上触摸,例如对于以下地图countArea(map, 0, 0)countArea(map, 1, 1)都将返回1:

A.
.A

附带说明一下,您不应将map用作变量名,因为它将掩盖内置的map()函数。

暂无
暂无

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

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