C - 島巡りの冒険 / Island Hopping Adventure 解説 by admin
Gemini 3.0 Flash (Thinking)Overview
This problem asks us to find the shortest path (minimum number of moves) from a starting island \(S\) to a goal island \(T\) in a graph where the \(N\) islands are treated as vertices and edges connect pairs of islands within distance \(D\) of each other.
Analysis
Reformulation as a Graph Problem
By treating each island as a “vertex” and each pair of reachable islands as an “edge,” this problem reduces to a classic single-source shortest path problem. - Number of vertices \(N\): up to 1500 - Edge condition: the Euclidean distance between two islands satisfies \(\sqrt{(X_i - X_j)^2 + (Y_i - Y_j)^2} \leq D\)
Optimization of Distance Computation
Computing the Euclidean distance involves a square root (sqrt), which can introduce floating-point errors when using floating-point numbers.
By squaring both sides of the inequality, we can perform the comparison using only integer arithmetic:
$\((X_i - X_j)^2 + (Y_i - Y_j)^2 \leq D^2\)$
This technique allows us to make exact comparisons without worrying about precision errors.
Shortest Path Algorithm
Since we are finding the shortest path in an unweighted graph (all edge lengths are 1), Breadth-First Search (BFS) is the optimal approach. With \(N = 1500\), precomputing distances between all pairs of islands to build an adjacency list (\(O(N^2)\)) would be fast enough. However, in this implementation, we efficiently check only “unvisited islands” during the search, eliminating unnecessary computations.
Algorithm
- Initialization:
- Initialize an array
distthat stores the shortest distance to each island with \(-1\) (unvisited), and setdist[S] = 0for the starting island. - Create a list
unvisitedof all unvisited islands. - Add the starting island \(S\) to the search queue
queue.
- Initialize an array
- Breadth-First Search (BFS):
- Dequeue an island \(u\) from the queue.
- For each island \(v\) in the
unvisitedlist, check whether the distance from island \(u\) is at most \(D\). - If the distance is at most \(D\):
- Update
dist[v] = dist[u] + 1. - If island \(v\) is the destination \(T\), output
dist[v]at that point and terminate. - Add island \(v\) to the queue and remove it from
unvisited.
- Update
- Termination:
- If the queue becomes empty without reaching \(T\), output \(-1\).
Complexity
- Time Complexity: \(O(N^2)\)
- Each island enters the queue at most once.
- At each step, we scan the
unvisitedlist. Since the distance check for any pair of islands is performed at most once, the overall complexity is \(O(N^2)\). When \(N=1500\), \(N^2 = 2.25 \times 10^6\), which comfortably fits within the time limit.
- Space Complexity: \(O(N)\)
- Storing the coordinate data, distance array, queue, and unvisited list requires \(O(N)\) memory.
Implementation Notes
Fast I/O: Since \(N\) is relatively large, reading all input at once using methods like
sys.stdin.read().split()can reduce execution time.Conversion to 0-indexed: The problem numbers islands from 1 to \(N\), but handling them as 0 to \(N-1\) in the program makes array index operations smoother.
Managing the Unvisited List: By updating the
unvisitedlist to avoid re-checking already visited islands, we improve the efficiency of the search.Source Code
import sys
from collections import deque
def solve():
# すべての入力を一括で読み込みます
input_data = sys.stdin.read().split()
if not input_data:
return
# 基本パラメータのパース
# N: 島の数, D: 一度に移動できる最大距離, S: 出発する島, T: 目的の島
N = int(input_data[0])
D = int(input_data[1])
S = int(input_data[2]) - 1 # 0-indexedに変換
T = int(input_data[3]) - 1 # 0-indexedに変換
# 各島の座標を読み込みます
X = [0] * N
Y = [0] * N
for i in range(N):
X[i] = int(input_data[4 + 2*i])
Y[i] = int(input_data[5 + 2*i])
# ユークリッド距離の比較を高速化するため、距離の2乗を計算しておきます
D2 = D * D
# 幅優先探索 (BFS) を用いて最短移動回数を求めます
# dist[i] は島 S から島 i までの最小移動回数を保持します
dist = [-1] * N
dist[S] = 0
queue = deque([S])
# まだ訪れていない島のリストを保持します
# これにより、探索済みの島を何度もチェックするのを避けます
unvisited = [i for i in range(N) if i != S]
while queue:
u = queue.popleft()
ux, uy = X[u], Y[u]
# 今回のステップで訪問できなかった島を保持するための新しいリスト
next_unvisited = []
for v in unvisited:
dx = ux - X[v]
dy = uy - Y[v]
# 浮動小数点の誤差を避けるため、2乗の状態で比較を行います
if dx * dx + dy * dy <= D2:
dist[v] = dist[u] + 1
# 目的地に到達した場合、即座に結果を出力して終了します
if v == T:
print(dist[v])
return
queue.append(v)
else:
# 到達できなかった島は次回の探索候補として残します
next_unvisited.append(v)
# 未訪問リストを更新
unvisited = next_unvisited
# キューが空になっても目的地 T に到達できなかった場合
print("-1")
if __name__ == '__main__':
solve()
This editorial was generated by gemini-3-flash-thinking.
投稿日時:
最終更新: