D - 交互移動ロボット / Alternating Movement Robot 解説 by admin
Gemini 3.8 Flash (High)Overview
This problem asks for the minimum number of moves to travel from the starting point \((1, 1)\) to the goal \((H, W)\) on an \(H \times W\) grid while strictly alternating between vertical and horizontal moves.
Analysis
Difference from Standard Shortest Path Problems
In standard grid shortest path problems (using Breadth-First Search: BFS), the search can be performed using only the information of “which cell \((r, c)\) we are currently in.” However, in this problem, there is a constraint on “whether the previous move was vertical or horizontal” (or equivalently, “whether the next move must be vertical or horizontal”). Therefore, even when at the same cell, the state where “we can only move vertically next” and the state where “we can only move horizontally next” must be distinguished as completely different situations.
State Expansion (Expanded Graph)
Thus, we consider a state that combines the “current cell \((r, c)\)” with the “direction \(t\) in which we can move next.”
- \(t = 0\): The next move is horizontal (left or right)
- \(t = 1\): The next move is vertical (up or down)
By expanding the state in this way, the transitions from each state are as follows: - From state \(((r, c), t = 0)\), we move to adjacent empty cells horizontally \((r, c \pm 1)\), resulting in the new state \(((r, c \pm 1), t = 1)\). - From state \(((r, c), t = 1)\), we move to adjacent empty cells vertically \((r \pm 1, c)\), resulting in the new state \(((r \pm 1, c), t = 0)\).
Since every move has a cost of \(1\), we can find the minimum number of moves by performing a Breadth-First Search (BFS) on this expanded graph.
Start and Goal
- Start: Since the first move can be either vertical or horizontal, we begin the search with both \(((1, 1), t = 0)\) and \(((1, 1), t = 1)\) as initial states with a cost of \(0\).
- Goal: As long as we eventually reach \((H, W)\), the value of \(t\) (whether the preceding move was vertical or horizontal) does not matter.
Algorithm
- Represent each state as a pair of the “cell index \(\text{idx} = r \times W + c\)” and the “movement direction \(t \in \{0, 1\}\)”.
- Prepare an array
distof size \(2 \times H \times W\) to track the shortest distances, initialized to \(-1\) (unvisited). - Set the distance of the starting states \(((1, 1), 0)\) and \(((1, 1), 1)\) to \(0\), and push them into the queue.
- Pop a state from the queue, and explore the next cells depending on the current \(t\):
- If \(t = 0\): Check the horizontally adjacent cells (left and right). If a cell is empty and unvisited, update the distance to the next state (\(t = 1\)) and push it into the queue.
- If \(t = 1\): Check the vertically adjacent cells (up and down). If a cell is empty and unvisited, update the distance to the next state (\(t = 0\)) and push it into the queue.
- The moment cell \((H, W)\) is reached during the search, output the number of moves at that point and terminate (due to the nature of BFS, the first time it is reached is guaranteed to be the minimum).
- If the queue becomes empty without reaching cell \((H, W)\), output
NONE.
Complexity
- Time Complexity: \(O(HW)\)
- The number of states (vertices) is \(V = 2HW\).
- Since there are at most \(2\) transitions (movement choices) from each vertex, the number of edges is \(E \leq 4HW\).
- The time complexity of BFS is \(O(V + E) = O(HW)\), which easily runs within the time limit under the constraints \(H, W \leq 1000\) (\(HW \leq 10^6\)).
- Space Complexity: \(O(HW)\)
- The distance array
distfor all states and the BFS queue require \(O(HW)\) memory.
- The distance array
Implementation Notes
Encoding States as Integers: By using bitwise operations to combine the cell index
idxand directiontinto(idx << 1) | t, a state can be managed as a single integer. This speeds up array access and helps reduce memory usage.Early Exit: Instead of checking when popping from the queue, immediately outputting the answer and terminating the moment we see that the next destination is cell \((H, W)\) avoids unnecessary exploration.
Source Code
import sys
def main():
input_data = sys.stdin.read().split()
if not input_data:
return
H = int(input_data[0])
W = int(input_data[1])
grid = [int(x) for x in input_data[2:]]
target_idx = H * W - 1
total_states = 2 * H * W
dist = [-1] * total_states
# 状態: (idx << 1) | t
# t = 0: 次の移動は横方向
# t = 1: 次の移動は縦方向
dist[0] = 0
dist[1] = 0
q = [0, 1]
head = 0
while head < len(q):
u = q[head]
head += 1
d = dist[u]
idx = u >> 1
t = u & 1
r = idx // W
c = idx % W
if t == 0:
# 横移動
if c > 0:
nidx = idx - 1
if grid[nidx] == 0:
nxt = (nidx << 1) | 1
if dist[nxt] == -1:
if nidx == target_idx:
print(d + 1)
return
dist[nxt] = d + 1
q.append(nxt)
if c + 1 < W:
nidx = idx + 1
if grid[nidx] == 0:
nxt = (nidx << 1) | 1
if dist[nxt] == -1:
if nidx == target_idx:
print(d + 1)
return
dist[nxt] = d + 1
q.append(nxt)
else:
# 縦移動
if r > 0:
nidx = idx - W
if grid[nidx] == 0:
nxt = (nidx << 1) | 0
if dist[nxt] == -1:
if nidx == target_idx:
print(d + 1)
return
dist[nxt] = d + 1
q.append(nxt)
if r + 1 < H:
nidx = idx + W
if grid[nidx] == 0:
nxt = (nidx << 1) | 0
if dist[nxt] == -1:
if nidx == target_idx:
print(d + 1)
return
dist[nxt] = d + 1
q.append(nxt)
print("NONE")
if __name__ == '__main__':
main()
This editorial was generated by gemini-3.8-flash-high.