AtCoder Beginner Contest 088 D – Grid Repainting をPython3で解く

Share

AtCoder上にある問題のうち、AtCoder Problemsでdiff 800以上と判定されているものを順番に解いていく企画。
基本的な考え方は全てコード中のコメントに入れてあるので、参照のこと。

出典:
AtCoder Beginner Contest 088 D – Grid Repainting

グリッドをBFSで全探索すれば解ける典型問題。すんなりと解けるようになっておきたい。

# AtCoder Beginner Contest 088 D - Grid Repainting
# https://atcoder.jp/contests/abc088/tasks/abc088_d
# tag: グリッド BFS 典型問題 すぬけ君 一人ゲーム

# 最短手数で (1, 1) から (H, W) までたどり着くルートを見つけ、
# その時通ったマス以外を全て黒に塗ったときが答え。
# BFS で最短距離を求めればいい。

from collections import deque
def main():
H, W = map(int, input().split())
field = [input() for _ in range(H)]

dist = [[0] * W for _ in range(H)]

# すでにある黒マスの数を数えておく
n_black = sum(row.count('#') for row in field)

# インデックスを合わせて、スタートは (0, 0)
# ゴールは (W-1, H-1) としておく
# グリッドをBFSで全探索しつつ、スタートからの
# 歩数を求めていく
moves = ((-1, 0), (1, 0), (0, -1), (0, 1))
queue = deque([(0, 0)])
while queue:
# 左から次の地点を取得(BFS)
x_now, y_now = queue.popleft()
dist_now = dist[y_now][x_now]

# 次の地点を見ていく
for dx, dy in moves:
x_nxt, y_nxt = x_now + dx, y_now + dy
# 範囲外ならスキップ
if not (0 <= x_nxt < W and 0 <= y_nxt < H):
continue
# 壁 or 探索済みならスキップ
if field[y_nxt][x_nxt] == '#' or dist[y_nxt][x_nxt] != 0:
continue
# 次の地点の距離を現在地 +1 に確定し、探索キューに入れる
dist[y_nxt][x_nxt] = dist_now + 1
queue.append((x_nxt, y_nxt))

# ゴールにたどり着けない場合
if dist[H-1][W-1] == 0:
print(-1)

# ゴールまでの歩数 + 1 マスの白マスが必要
# 残りを全て黒マスにする(もともと黒マスのところはそのまま)
else:
print((H * W) - dist[H-1][W-1] - 1 - n_black)

main()
Share

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です