D - 迷路からの脱出 / Escape from the Maze Editorial by admin
Gemini 3.0 FlashOverview
In a maze composed of an \(N \times M\) grid, this is a shortest path problem where we move from start to goal while minimizing the number of walls (#) destroyed.
Analysis
This problem can be solved as a shortest path problem by treating the grid as a graph. Each cell is considered a “vertex,” and movement to adjacent cells is considered an “edge.”
We define the cost of movement as follows:
- If the destination cell is a passage (.): cost \(0\)
- If the destination cell is a wall (#): cost \(1\) (because we destroy the wall to turn it into a passage)
With this definition, the answer we seek is “the minimum cost from cell \((1, 1)\) to cell \((N, M)\).”
For a normal maze (where all movement costs are \(1\)), breadth-first search (BFS) would suffice, but since there are \(2\) types of costs, \(0\) and \(1\), a simple queue-based BFS cannot compute the correct answer. In this special situation where “edge weights are only \(0\) or \(1\),” we can efficiently find the shortest path using an algorithm called 0-1 BFS.
Algorithm
0-1 BFS
0-1 BFS is a technique that finds shortest distances using a double-ended queue (deque).
- Initialization: Initialize the distance array
distto infinity, and set the distance of the starting point to \(0\). - Exploration: Pop the current cell from the front of the
dequeand examine the \(4\) adjacent directions. - Update:
- If the cost to the destination is \(0\) (passage):
- If the distance can be improved with the current distance, update
distand add that cell to the front (left) of thedeque.
- If the distance can be improved with the current distance, update
- If the cost to the destination is \(1\) (wall):
- If the distance can be improved with the current distance \(+1\), update
distand add that cell to the back (right) of thedeque.
- If the distance can be improved with the current distance \(+1\), update
- If the cost to the destination is \(0\) (passage):
- Termination: Repeat until the
dequeis empty or the goal is reached.
By prioritizing exploration of cost \(0\) movements, this works like a simplified version of Dijkstra’s algorithm, finding the shortest path while keeping the computational complexity low.
Complexity
- Time complexity: \(O(N \times M)\)
- Since each cell is popped from the
dequeat most once, the algorithm finishes in time proportional to the number of cells in the grid.
- Since each cell is popped from the
- Space complexity: \(O(N \times M)\)
- The array holding the grid state and the array
distholding the shortest distance for each cell each use \(N \times M\) memory.
- The array holding the grid state and the array
Implementation Notes
Using
deque: In Python, usecollections.deque. The key point is to useappendleft()for cost \(0\) andappend()for cost \(1\).Boundary check: Always verify that the destination cell is within the range \(0 \le r < N\) and \(0 \le c < M\).
Early termination: In 0-1 BFS, when a cell is popped from the
deque, its shortest distance is finalized. Therefore, we can output the answer and terminate the moment the goal cell is popped.Source Code
import sys
from collections import deque
def solve():
# 標準入力からすべてのデータを読み込み、空白や改行で分割します。
# これにより、N, M およびグリッドの各行を効率的に取得できます。
input_data = sys.stdin.read().split()
if not input_data:
return
# N: 行数, M: 列数
N = int(input_data[0])
M = int(input_data[1])
# グリッドの状態を文字列のリストとして取得します
grid = input_data[2:]
# 各マスに到達するために破壊した壁の最小数を保持する2次元配列
# 初期値として十分に大きな値(無限大)を設定します
inf = 10**9
dist = [[inf] * M for _ in range(N)]
# スタート地点 (0, 0) のコストは 0 です
dist[0][0] = 0
# 0-1 BFS(最短経路アルゴリズムの一種)のためのデック
# (行, 列) のタプルを格納します
dq = deque([(0, 0)])
# 移動可能な4方向(右、左、下、上)
directions = ((0, 1), (0, -1), (1, 0), (-1, 0))
while dq:
# デックの先頭から現在のマスを取り出します
r, c = dq.popleft()
d = dist[r][c]
# ゴール地点 (N-1, M-1) に到達した場合、その時点のコストを出力して終了します
# 0-1 BFSでは、最初に取り出したときがそのマスへの最短経路となります
if r == N - 1 and c == M - 1:
print(d)
return
# 隣接する4マスを探索します
for dr, dc in directions:
nr, nc = r + dr, c + dc
# グリッドの範囲内であるか確認します
if 0 <= nr < N and 0 <= nc < M:
# 移動先のマスが壁(#)なら破壊コスト 1、通路(.)ならコスト 0
weight = 1 if grid[nr][nc] == '#' else 0
# より少ない壁破壊数でそのマスに到達できる場合、更新を行います
if dist[nr][nc] > d + weight:
dist[nr][nc] = d + weight
if weight == 0:
# コスト 0 の移動はデックの先頭に追加し、優先的に探索します
dq.appendleft((nr, nc))
else:
# コスト 1 の移動はデックの末尾に追加します
dq.append((nr, nc))
if __name__ == '__main__':
solve()
This editorial was generated by gemini-3-flash-preview.
posted:
last update: