公式
C - 島巡りの冒険 / Island Hopping Adventure 解説
by
C - 島巡りの冒険 / Island Hopping Adventure 解説
by
kyopro_friends
この問題は BFS (幅優先探索)により解くことができます。 島 \(S\) のみをキューに入れた状態からスタートし、キューの先頭から島を取り出しては、各島がそこから直接到達可能か調べ、到達可能かつ未踏の島であれば移動回数を記録してキューに追加します。
各島から各島へ到達可能であるかを高々 \(1\) 回調べるため、計算量は \(O(N^2)\) になります。
なお、距離の計算を問題文の数式の通りに計算し、浮動小数点数を用いて比較を行うと、誤差の影響で誤判定することがあります。例えば \(x=958043599\) のとき sqrt(x * x + 1) <= x は True となります。
両辺を 2 乗することで、整数の範囲で比較を行うことができ、誤差の影響を避けることができます。
実装例 (C++)
#include<bits/stdc++.h>
using namespace std;
int main(){
int n, s, t;
long long d;
cin >> n >> d >> s >> t;
s--, t--;
vector<pair<long long, long long>>xy(n);
for(int i=0; i<n; i++) cin >> xy[i].first >> xy[i].second;
auto is_reachable=[&](int i, int j){
auto [xi, yi] = xy[i];
auto [xj, yj] = xy[j];
return (xi - xj) * (xi - xj) + (yi - yj) * (yi - yj) <= d * d;
};
int INF = 1e9;
vector<int>dist(n, INF);
dist[s] = 0;
queue<int>q;
q.push(s);
while(q.size() > 0){
int v = q.front();
q.pop();
for(int vv=0; vv<n; vv++){
if(is_reachable(v, vv) && dist[vv] == INF){
dist[vv] = dist[v] + 1;
q.push(vv);
}
}
}
if(dist[t] == INF){
cout << -1 << endl;
}else{
cout << dist[t] << endl;
}
}
実装例 (Python)
N, D, S, T = map(int, input().split())
S -= 1
T -= 1
XY = []
for _ in range(N):
X, Y = map(int,input().split())
XY.append((X, Y))
def is_reachable(i, j):
Xi, Yi = XY[i]
Xj, Yj = XY[j]
return (Xi - Xj) ** 2 + (Yi - Yj) ** 2 <= D ** 2
INF = 10**18
dist = [INF]*N
dist[S] = 0
q = [S]
for v in q:
for vv in range(N):
if is_reachable(v, vv) and dist[vv] == INF:
dist[vv] = dist[v]+1
q.append(vv)
if dist[T] == INF:
print(-1)
else:
print(dist[T])
投稿日時:
最終更新:
