題目描述:node
Eagle Jump公司正在開發一款新的遊戲。瀧本一二三做爲其員工,得到了提早試玩的機會。如今她正在試圖經過一個迷宮。ios
這個迷宮有一些特色。爲了方便描述,咱們對這個迷宮創建平面直角座標系。迷宮中有兩條平行直線 L\_1:Ax+By+C\_1=0L1:Ax+By+C1=0, L\_2:Ax+By+C\_2=0L2:Ax+By+C2=0,還有 nn 個圓 C\_i:(x-x\_i)^2+(y-y\_i)^2={r\_i}^2Ci:(x−xi)2+(y−yi)2=ri2。角色在直線上、圓上、圓內行走不消耗體力。在其餘位置上由SS點走到TT點消耗的體力爲SS和TT的歐幾里得距離。c++
瀧本一二三想從 L\_1L1 出發,走到 L\_2L2 。請計算最少須要多少體力。spa
輸入:code
第一行五個正整數 n,A,B,C\_1,C\_2n,A,B,C1,C2 (1\le n \le 1000, -10000 \le A,B,C\_1,C\_2 \le 10000)(1≤n≤1000,−10000≤A,B,C1,C2≤10000),其中 A,BA,B 不一樣時爲 0。遊戲
接下來 nn 行每行三個整數 x,y,r(-10000 \le x,y \le 10000, 1\le r \le 10000)x,y,r(−10000≤x,y≤10000,1≤r≤10000) 表示一個圓心爲 (x,y)(x,y),半徑爲 rr 的圓。ci
輸出:開發
僅一行一個實數表示答案。與標準答案的絕對偏差或者相對偏差不超過 10^{-4}10−4 即算正確。it
樣例輸入io
2 0 1 0 -4 0 1 1 1 3 1
樣例輸出
0.236068
L1 到 L2 之間連邊權值 |C1−C2| / √ A2+B2
線 L 與圓 i 之間連邊權值 max(0, d(Oi , L1) − ri)
圓 i 與圓 j 之間連邊權值 max(0, d(Oi , Oj ) − ri − rj )
求 L1 到 L2 的最短路便可。
#include<bits/stdc++.h> #define ios1 ios::sync_with_stdio(0) #define ios2 cin.tie(0) #define inf 0x3f3f3f3f using namespace std; const int maxn = 5000; int n, A, B, C1, C2; double Map[maxn][maxn]; struct node{ double x, y, r; }circle[maxn]; void init() { for(int i = 0 ; i <= n + 1; i++){ for(int j = 0; j <= n + 1; j++) { if(i == j)Map[i][j] = 0; else Map[i][j] = inf; } } } bool cmp (node p, node q) { if(p.x == q.x)return p.y < p.y; return p.x < p.y; } double dis[maxn]; bool vis[maxn]; void Dijkstra() { for (int i = 0; i <= n+1; i++) { dis[i] = Map[0][i]; } vis[0] = 1; for (int i = 0; i < n+1; i++) { double MIN = inf; int x = -1; for (int j = 0; j <= n+1; j++) { if (!vis[j] && dis[j]<MIN) { MIN = dis[j]; x = j; } } vis[x] = 1; for (int j = 0; j <= n+1; j++) { if (!vis[j] && MIN + Map[x][j]<dis[j]) { dis[j] = Map[x][j] + MIN; } } } } int main() { ios1; ios2; while(cin >> n >> A >> B >> C1 >> C2) { for(int i = 1; i <= n; i++) { cin >> circle[i].x >> circle[i].y >> circle[i].r; } init(); Map[0][n+1] = Map[n+1][0] = abs(C1-C2)/sqrt(A*A+B*B); for(int i = 1; i <= n; i++) { double k = abs(A*circle[i].x + B*circle[i].y + C1)/sqrt(A*A+B*B) - circle[i].r; if(k < 0)k = 0; Map[0][i] = Map[i][0] = k; } for(int i = 1; i <= n; i++) { double k = abs(A*circle[i].x + B*circle[i].y + C2)/sqrt(A*A+B*B) - circle[i].r; if(k < 0)k = 0; Map[i][n+1] = Map[n+1][i] = k; } for(int i = 1 ; i <= n; i++) { for(int j = 1; j <= n; j++) { if(i != j){ double k = sqrt(abs(circle[i].x - circle[j].x) * abs(circle[i].x - circle[j].x) + abs(circle[i].y - circle[j].y) * abs(circle[i].y - circle[j].y)) - circle[i].r - circle[j].r; if(k < 0)k = 0; Map[i][j] = k; } } } memset(vis, 0, sizeof(vis)); Dijkstra(); printf("%lf\n", dis[n+1]); } return 0; }