Leetcode 廣搜 深搜 掃雷遊戲(529)

2022-03-01 03:44:50 字數 4053 閱讀 1230

讓我們一起來玩掃雷遊戲!

給定乙個代表遊戲板的二維字元矩陣。 'm' 代表乙個未挖出的地雷,'e' 代表乙個未挖出的空方塊,'b' 代表沒有相鄰(上,下,左,右,和所有4個對角線)地雷的已挖出的空白方塊,數字('1' 到 '8')表示有多少地雷與這塊已挖出的方塊相鄰,'x' 則表示乙個已挖出的地雷。

如果乙個地雷('m')被挖出,遊戲就結束了- 把它改為'x'

如果乙個沒有相鄰地雷的空方塊('e')被挖出,修改它為('b'),並且所有和其相鄰的方塊都應該被遞迴地揭露。

如果乙個至少與乙個地雷相鄰的空方塊('e')被挖出,修改它為數字('1'到'8'),表示相鄰地雷的數量。

如果在此次點選中,若無更多方塊可被揭露,則返回面板。

示例 1:

輸入: 

[['e', 'e', 'e', 'e', 'e'],

['e', 'e', 'm', 'e', 'e'],

['e', 'e', 'e', 'e', 'e'],

['e', 'e', 'e', 'e', 'e']]

click : [3,0]

輸出:

[['b', '1', 'e', '1', 'b'],

['b', '1', 'm', '1', 'b'],

['b', '1', '1', '1', 'b'],

['b', 'b', 'b', 'b', 'b']]

示例 2:

輸入: 

[['b', '1', 'e', '1', 'b'],

['b', '1', 'm', '1', 'b'],

['b', '1', '1', '1', 'b'],

['b', 'b', 'b', 'b', 'b']]

click : [1,2]

輸出:

[['b', '1', 'e', '1', 'b'],

['b', '1', 'x', '1', 'b'],

['b', '1', '1', '1', 'b'],

['b', 'b', 'b', 'b', 'b']]

注意:

輸入矩陣的寬和高的範圍為 [1,50]。

點選的位置只能是未被挖出的方塊 ('m' 或者 'e'),這也意味著面板至少包含乙個可點選的方塊。

輸入面板不會是遊戲結束的狀態(即有地雷已被挖出)。

簡單起見,未提及的規則在這個問題中可被忽略。例如,當遊戲結束時你不需要挖出所有地雷,考慮所有你可能贏得遊戲或標記方塊的情況。

理解題意並不複雜,典型的搜尋題,深搜廣搜都可以,**為廣搜:

from queue import queue

from pprint import pprint

# bfs

# time: o(mn), space: o(mn), m n表示輸入陣列行列數

class solution:

def get_cnt(self, next, x, y, rows, columns, board):

'''獲取周圍炸彈個數'''

cnt = 0

for i in range(8):

tx = x + next[i][0]

ty = y + next[i][1]

if 0 <= tx < rows and 0 <= ty < columns and board[tx][ty] == 'm':

cnt += 1

return cnt

def updateboard(self, board, click):

if not board:

return board

if board[click[0]][click[1]] == 'm':

board[click[0]][click[1]] = 'x'

return board

rows, columns = len(board), len(board[0])

next = [

[0, 1],

[1, 0],

[0, -1],

[-1, 0],

[1, 1], # 右下

[1, -1],

[-1, -1],

[-1, 1]

]# 點選的位置周圍有炸彈,修改為炸彈數量,結束

cnt = self.get_cnt(next, click[0], click[1], rows, columns, board)

if cnt:

board[click[0]][click[1]] = str(cnt)

return board

q = queue()

q.put(click)

board[click[0]][click[1]] = 'b'

while not q.empty():

x, y = q.get()

for i in range(8):

tx = x + next[i][0]

ty = y + next[i][1]

if 0 <= tx < rows and 0 <= ty < columns and board[tx][ty] == 'e':

cnt = self.get_cnt(next, tx, ty, rows, columns, board) # 周圍炸彈個數

if not cnt:

board[tx][ty] = 'b'

q.put([tx, ty])

else:

board[tx][ty] = str(cnt) # 周圍有炸彈,修改為炸彈數量,不計入佇列

return board

# [["b", "b", "b", "b", "b", "b", "1", "1"],

# ["b", "1", "1", "1", "b", "b", "1", "m"],

# ["1", "2", "m", "1", "b", "b", "1", "1"],

# ["m", "2", "1", "1", "b", "b", "b", "b"],

# ["1", "1", "b", "b", "b", "b", "b", "b"],

# ["b", "b", "b", "b", "b", "b", "b", "b"],

# ["b", "1", "2", "2", "1", "b", "b", "b"],

# ["b", "1", "m", "m", "1", "b", "b", "b"]]

s = solution()

ans = s.updateboard([["b", "b", "b", "b", "b", "b", "1", "e"],

["b", "1", "1", "1", "b", "b", "1", "m"],

["1", "2", "m", "1", "b", "b", "1", "1"],

["m", "2", "1", "1", "b", "b", "b", "b"],

["1", "1", "b", "b", "b", "b", "b", "b"],

["b", "b", "b", "b", "b", "b", "b", "b"],

["b", "1", "2", "2", "1", "b", "b", "b"],

["b", "1", "m", "m", "1", "b", "b", "b"]],

[0, 7])

# ans = s.updateboard([['e', 'e', 'e', 'e', 'e'],

# ['e', 'e', 'm', 'e', 'e'],

# ['e', 'e', 'e', 'e', 'e'],

# ['e', 'e', 'e', 'e', 'e']], [3, 0])

pprint(ans)

廣搜和深搜

一般來說,廣搜常用於找單一的最短路線,或者是規模小的路徑搜尋,它的特點是 搜到就是最優解 而深搜用於找多個解或者是 步數 已知 好比3步就必需達到前提 的標題,它的空間效率高,然則找到的不必定是最優解,必需記實並完成全數搜尋,故一般情況下,深搜需要很是高效的剪枝 優化 像搜尋最短路徑這些的很顯著若是...

搜尋(深搜 廣搜)

我記得在遙遠的2017年,我會敲的搜尋也只有暴力列舉了。那個時候的我深搜剛會一丟丟,所以也只配切切水題,然而經常死迴圈re那是肯定的。如今的我因為在多次比賽中都死於搜尋,那就必須得認真磕一下了。其實是這樣的 我眼裡認為的暴力就真的只是暴力,暴力無非就兩種 列舉打表和模擬。然而在這麼多次比賽後,我總能...

深搜和廣搜

深度優先搜尋屬於圖演算法的一種,英文縮寫為dfs即depth first search.其過程簡要來說是對每乙個可能的分支路徑深入到不能再深入為止,而且每個節點只能訪問一次 採用的搜尋方法的特點是盡可能先對縱深方向進行搜尋。基本思路 深度優先遍歷圖的方法是,從圖中某頂點v出發 1 訪問頂點v 2 依...