D - 迷宮からの脱出 / Escape from the Labyrinth 解説 by admin 印刷ページ
GPT 5.2 HighOverview
We model the situation where Takahashi (the player) and up to \(2\) guard robots move simultaneously within the same maze as a shortest-path search on state transitions (BFS), and determine whether Takahashi can reach the exit in the minimum number of turns.
Analysis
Key Observations
- This problem states that “Takahashi moves optimally,” so it appears to be a typical shortest-turn problem, but since the robots also move, it is not a simple shortest path problem.
- However, the robots’ movements are:
- Avoiding walls (moving only through corridors),
- Based solely on Takahashi’s position after his move in that turn,
- Deterministically decided according to the rules.
In other words, if we know “Takahashi’s position” and “each robot’s position” at a given turn, the next state is uniquely determined (aside from Takahashi’s choice of action).
Why a Naive Approach is Difficult
- Running BFS on “Takahashi’s position alone” will result in WA. Since different robot positions lead to different dangers, the same cell can represent entirely different situations.
- Conversely, approaches like “increase the turn count and search for the optimal action via simulation” are unstable because cycles (returning to the same situation) can occur, making it unclear when to stop.
Solution Strategy
- Run BFS with the state defined as (Takahashi’s position, robot positions (up to 2)).
- With BFS, the first time we reach the exit is guaranteed to be the minimum number of turns.
- Since \(N, M \le 8\), the maximum number of cells is \(64\), and there are at most \(2\) robots, so the number of states is at most around \(64^3 = 262144\).
Algorithm
State Definition
- Each cell is converted to an ID \(v \in [0, NM)\).
- The state is:
- \(K=0\): \((t)\)
- \(K=1\): \((t, r_1)\)
- \(K=2\): \((t, r_1, r_2)\)
where \(t\) is Takahashi’s position and \(r_i\) is the position of robot \(i\).
Transitions (One Turn)
One BFS step corresponds to “one turn.” From the current state, we construct the next state in the following order:
Enumerate Takahashi’s action candidates
Up, down, left, right, and stay (up to 5 options), allowing only corridor cells.Capture check 1 (after Takahashi moves)
If Takahashi’s destinationtocoincides with a robot’s position, this move fails (no transition).Escape check (after Takahashi moves)
Ifto == G, the escape is successful at this point.
Since we use BFS, the turn countdepth+1at this point is the minimum.Robot movement (simultaneous)
For each robot, among the candidates (up, down, left, right, stay):- Choose the one that minimizes the Manhattan distance to Takahashi’s position
to. - If tied, use the priority order: “up → down → left → right → stay.”
- Choose the one that minimizes the Manhattan distance to Takahashi’s position
This uniquely determines the destination nr for each robot.
Capture check 2 (after robots move)
If any robot’s new position satisfiesnr == to, this move fails (no transition).Add to queue if unvisited
Revisiting the same state is meaningless (it would likely repeat the same sequence), so we manage this with avisitedset.
State Compression (Implementation)
Since \(NM \le 64\), each position can be represented with 6 bits.
In the code:
- Takahashi: lower 6 bits
- Robot 1: next 6 bits
- Robot 2: next 6 bits
These are packed into a single integer, and visited is managed as a set.
Complexity
The number of states is at most \(64^{1+K}\), and from each state, the branching factor is Takahashi’s maximum of 5 moves. The robot movement computation also involves at most 5 candidates per robot, so it is constant.
- Time complexity: \(O(64^{1+K})\) (strictly \(O(5 \cdot 5K \cdot 64^{1+K})\), but constant factors)
- Space complexity: \(O(64^{1+K})\) (visited states and queue)
Implementation Notes
The order of capture checks is crucial. You must strictly follow the problem statement’s order:
“Capture check after Takahashi moves → escape check → robot movement → capture check.”
Deviating from this will result in WA.The robot candidates require the priority order “up, down, left, right, stay,” so the candidate list should be constructed in that order. If distances are equal, the one appearing first is chosen (in the code,
rob_cands[pos]is maintained in this order).We can output the answer the moment we find
to == Gduring BFS because BFS explores in ascending order of turn count (depth).Source Code
import sys
from collections import deque
def main():
input = sys.stdin.readline
N, M, K = map(int, input().split())
Sr, Sc = map(int, input().split())
Gr, Gc = map(int, input().split())
Sr -= 1; Sc -= 1
Gr -= 1; Gc -= 1
robots_rc = []
for _ in range(K):
pr, qc = map(int, input().split())
robots_rc.append((pr - 1, qc - 1))
grid = [input().strip() for _ in range(N)]
cells = N * M
def cid(r, c): return r * M + c
passable = [False] * cells
for r in range(N):
row = grid[r]
for c in range(M):
if row[c] == '.':
passable[cid(r, c)] = True
r_of = [i // M for i in range(cells)]
c_of = [i % M for i in range(cells)]
# Takahashi moves (U, D, L, R, Stay) within passable cells
dirs = [(-1, 0), (1, 0), (0, -1), (0, 1), (0, 0)]
taka_moves = [[] for _ in range(cells)]
for v in range(cells):
if not passable[v]:
continue
r, c = r_of[v], c_of[v]
lst = []
for dr, dc in dirs:
nr, nc = r + dr, c + dc
if 0 <= nr < N and 0 <= nc < M:
nv = cid(nr, nc)
if passable[nv]:
lst.append(nv)
taka_moves[v] = lst
# Robot candidate moves in priority order (U, D, L, R, Stay)
rob_cands = [[] for _ in range(cells)]
for v in range(cells):
if not passable[v]:
continue
r, c = r_of[v], c_of[v]
cand = []
for dr, dc in dirs:
nr, nc = r + dr, c + dc
if 0 <= nr < N and 0 <= nc < M:
nv = cid(nr, nc)
if passable[nv]:
cand.append(nv)
rob_cands[v] = cand
def robot_move(pos, target):
tr, tc = r_of[target], c_of[target]
best = None
bestd = 10**9
for nv in rob_cands[pos]: # already in priority order
d = abs(r_of[nv] - tr) + abs(c_of[nv] - tc)
if d < bestd:
bestd = d
best = nv
return best
S = cid(Sr, Sc)
G = cid(Gr, Gc)
robot_ids = [cid(r, c) for (r, c) in robots_rc]
# Pack state into int using 6 bits per position (cells<=64)
MASK = 63
if K == 0:
init = S
elif K == 1:
init = S | (robot_ids[0] << 6)
else:
init = S | (robot_ids[0] << 6) | (robot_ids[1] << 12)
q = deque([(init, 0)])
visited = {init}
while q:
state, depth = q.popleft()
if K == 0:
t = state
r1 = r2 = None
elif K == 1:
t = state & MASK
r1 = state >> 6
r2 = None
else:
t = state & MASK
r1 = (state >> 6) & MASK
r2 = state >> 12
for to in taka_moves[t]:
# Capture check 1
if K == 1:
if to == r1:
continue
elif K == 2:
if to == r1 or to == r2:
continue
turn = depth + 1
# Escape check
if to == G:
print(turn)
return
# Robots move + capture check 2
if K == 0:
ns = to
elif K == 1:
nr1 = robot_move(r1, to)
if nr1 == to:
continue
ns = to | (nr1 << 6)
else:
nr1 = robot_move(r1, to)
nr2 = robot_move(r2, to)
if nr1 == to or nr2 == to:
continue
ns = to | (nr1 << 6) | (nr2 << 12)
if ns not in visited:
visited.add(ns)
q.append((ns, depth + 1))
print(-1)
if __name__ == "__main__":
main()
This editorial was generated by gpt-5.2-high.
投稿日時:
最終更新: