New Game!(牛客賽)——Dijkstra最短路徑
阿新 • • 發佈:2018-12-13
題目描述
Eagle Jump公司正在開發一款新的遊戲。Hifumi Takimoto作為其中的員工,獲得了提前試玩的機會。現在她正在試圖通過一個迷宮。 這個迷宮有一些特點。為了方便描述,我們對這個迷宮建立平面直角座標系。迷宮中有兩條平行直線 L1:Ax+By+C1=0, L2:Ax+By+C2=0,還有 n 個圓 。角色在直線上、圓上、園內行走不消耗體力。在其他位置上由S點走到T點消耗的體力為S和T的歐幾里得距離。 Hifumi Takimoto想從 L1 出發,走到 L2 。請計算最少需要多少體力。
輸入描述:
第一行五個正整數 n,A,B,C1,C2 (1≤ n ≤ 1000, -10000 ≤ A,B,C1,C2 ≤ 10000),其中 A,B 不同時為 0。 接下來 n 行每行三個整數 x,y,r(-10000 ≤ x,y ≤ 10000, 1≤ r ≤ 10000) 表示一個圓心為 (x,y),半徑為 r 的圓。
輸出描述:
僅一行一個實數表示答案。與正確結果的絕對誤差或者相對誤差不超過 10-4 即算正確。
示例1
輸入
2 0 1 0 -4 0 1 1 1 3 1
輸出
0.236068
程式碼
#include<iostream> #include<cstring> #include<algorithm> #include<set> #include<math.h> using namespace std; struct Circle { double x; double y; double r; }; int n; double A, B, C1, C2; Circle cir[1001]; //-----------------------Dijkstra------------------ struct Edge { int v; double w; int next; }; int p[2000]; Edge e[2000000]; int eid; void init() { memset(p, -1, sizeof(p)); eid = 0; } void Insert(int u, int v, double w) { e[eid].v = v; e[eid].w = w; e[eid].next = p[u]; p[u] = eid++; } typedef pair<int, int> PII; set<PII, less<PII>> min_heap; double dist[2000]; //儲存單源最短路徑 int vis[2000]; //標記每個頂點是否被選取 bool dijkstra(int s) { //初始化 memset(vis, 0, sizeof(vis)); //memset(dist, 0x3f, sizeof(dist)); for (int i = 0; i < 2000; i++) { dist[i] = 100000000; } min_heap.insert(make_pair(0, s)); dist[s] = 0; for (int i = 0; i < n+2; ++i) { if (min_heap.size() == 0) { return false; } auto iter = min_heap.begin(); int v = iter->second; min_heap.erase(*iter); vis[v] = 1; for (int j = p[v]; j != -1; j = e[j].next) { int x = e[j].v; if (!vis[x] && dist[v] + e[j].w < dist[x]) { min_heap.erase(make_pair(dist[x], x)); dist[x] = dist[v] + e[j].w; min_heap.insert(make_pair(dist[x], x)); } } } return true; } //-------------------------------------------------- int main() { cin >> n >> A >> B >> C1 >> C2; for (int i = 0; i < n; i++) { cin >> cir[i].x >> cir[i].y >> cir[i].r; } init(); for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { double dis = sqrt( (cir[i].x - cir[j].x)*(cir[i].x - cir[j].x) + (cir[i].y - cir[j].y)*(cir[i].y - cir[j].y) ) - cir[i].r - cir[j].r; if (dis < 0) { Insert(i + 1, j + 1, 0); Insert(j + 1, i + 1, 0); } else { Insert(i + 1, j + 1, dis); Insert(j + 1, i + 1, dis); } } } for (int i = 0; i < n; i++) { double dis = abs(A * cir[i].x + B * cir[i].y + C1) / sqrt(A*A + B*B) - cir[i].r; if (dis < 0) { Insert(i + 1, n + 1, 0); Insert(n + 1, i + 1, 0); } else { Insert(i + 1, n + 1, dis); Insert(n + 1, i + 1, dis); } } for (int i = 0; i < n; i++) { double dis = abs(A * cir[i].x + B * cir[i].y + C2) / sqrt(A*A + B*B) - cir[i].r; if (dis < 0) { Insert(i + 1, n + 2, 0); Insert(n + 2, i + 1, 0); } else { Insert(i + 1, n + 2, dis); Insert(n + 2, i + 1, dis); } } Insert(n + 1, n + 2, abs(C1 - C2) / sqrt(A*A + B*B)); Insert(n + 2, n + 1, abs(C1 - C2) / sqrt(A*A + B*B)); dijkstra(n + 1); cout << dist[n + 2] << endl; return 0; }