作者:王一哲
日期:2025年12月12日
ZeroJudge 題目連結:
n700. 蝸牛的踩地雷攻略 3 (點方塊)
解題想法
為了不要檢查是否出界,我習慣在地圖的最右側、最下方加上用不到的符號當作哨兵。用自訂函式 count 計算周圍 8 格的地雷數量,再用另一個自訂函式 reveal 翻開格子,reveal 之中是用 BFS 找出所有可以翻開的格子,同時將翻開後的地圖儲存到另一個二維串列之中。
Python 程式碼
使用時間約為 24 ms,記憶體約為 3.8 MB,通過測試。
from collections import deque
def count(grid, r, c): # 計算周圍 8 格的地雷數量
cnt = 0 # 地雷數量
for dr, dc in ((0, 1), (1, 1), (1, 0), (1, -1), (0, -1), (-1, -1), (-1, 0), (-1, 1)):
nr, nc = r+dr, c+dc
if grid[nr][nc] == '*': cnt += 1
return cnt
def reveal(grid, result, ri, ci, n, m): # 翻開格子,代入地圖 grid,結果 result,位置 (ri, ci),維度 n*m
visited = [[False]*(m+1) for _ in range(n+1)] # 是否已走訪
que = deque([(ri, ci)]) # 待走訪的位置
visited[ri][ci] = True # (ri, ci) 已走訪
while que: # 如果 que 還有資料繼續執行
r, c = que.popleft() # 從 que 開頭讀取並移除資料
cnt = count(grid, r, c) # 計算 (r, c) 周圍的地雷數量
if cnt == 0: # 如果周圍沒有地雷
result[r][c] = '_' # 翻開,是空地
# 檢查周圍 8 格,如果還沒有出界、沒有走訪、是未翻開的格子
for dr, dc in ((0, 1), (1, 1), (1, 0), (1, -1), (0, -1), (-1, -1), (-1, 0), (-1, 1)):
nr, nc = r+dr, c+dc
if grid[nr][nc] != '@' and not visited[nr][nc] and grid[nr][nc] == '#':
visited[nr][nc] = True # (nr, nc) 已走訪
que.append((nr, nc)) # (nr, nc) 加入 que
else: result[r][c] = str(cnt) # 周圍有地雷,填入地雷的數量
def main(): # 主程式
n, m, ri, ci = map(int, input().split()) # 地圖維度 n*m,起點 (ri, ci)
grid = [list(input().strip() + '@') for _ in range(n)] # 最右側加上 @ 作為哨兵
grid.append(['@']*(m+1)) # 最下方加 m+1 個 @ 作為哨兵
result = [['#']*m for _ in range(n)] # 儲存結果用的 n*m 二維串列
ri -= 1; ci -= 1 # 配合索引值,ri, ci 減 1
reveal(grid, result, ri, ci, n, m) # 呼叫 reveal 求解
for row in result: print("".join(row)) # 印出答案
if __name__ == '__main__':
main()