[英]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.