考えて競プロする

プログラミングコンテストの問題をどう考えて解いたかを記録していくブログです。使用言語はPython3

ABC075-B - Minesweeper を解く

ABC075-B - Minesweeper

 

'#' を地雷と見立てて、実際のマインスイーパーのように

隣接地雷数を記載する問題

 

左上から右下にかけて全マスを探索していって

'#' ならそのままにする

'.' なら 隣接八近傍を確認して '#' の数に書き換える

という処理をしていく

 

注意したいのは、端のマスの処理だ

list を使って処理を書く場合は、存在しないマスを参照しようとして

エラーになってしまわないよう気をつける必要がある

 

以上を踏まえて書いたコードを以下に示す

 

提出したコード

# 入力
H,W=map(int,input().split())

l=[]
for i in range(H):
  l.append(list(input()))

for i in range(H):
  for j in range(W):
    # 地雷数のカウンタ
    c=0

    # '#'の場合はなにもしない
    if l[i][j]=='#':
      pass

    # '#'以外の場合
    else:
      # 左上
      if 0<i and 0<j and l[i-1][j-1]=='#':
        c+=1
      # 上
      if 0<i and l[i-1][j]=='#':
        c+=1
      # 右上
      if 0<i and j<W-1 and l[i-1][j+1]=='#':
        c+=1
      # 左
      if 0<j and l[i][j-1]=='#':
        c+=1
      # 右
      if j<W-1 and l[i][j+1]=='#':
        c+=1
      # 左下
      if i<H-1 and 0<j and l[i+1][j-1]=='#':
        c+=1
      # 下
      if i<H-1 and l[i+1][j]=='#':
        c+=1
      # 右下
      if i<H-1 and j<W-1 and l[i+1][j+1]=='#':
        c+=1

      # 地雷隣接数を記載
      l[i][j]=str(c)

# 出力
for i in range(H):
  print(''.join(l[i]))

 

提出結果はACでした

 

8方向それぞれに対して添字を気にしながら処理を書くのは

中々バグらせやすく、何回か書き直しをする羽目になった

 

解説では、8方向に対する差分量を配列にもつやり方を採用しており

バグりにくい良い実装が書かれていた

興味のある方は是非ご覧になってください