牛客國慶集訓派對Day1___L New Game!——最短路
阿新 • • 發佈:2018-12-13
題目連結:傳送門
題目大意:
給出兩條平行線和個圓,計算從一條線走到另一條線所消耗的體力。同時,在線上、圓上、園內走不消耗體力,求體力的最小花費。
解題思路:
一開始沒想到是最短路,後來仔細一想,除了最短路也沒啥其他的了。將線和圓都想象成一個個點,每個點之間的距離滿足以下關係: 到 之間連邊權值 線與圓之間連邊權值 圓與圓之間連邊權值 最後求最短路即可
程式碼思路:
注意要用double,double的絕對值是fabs函式
核心:將線和圓看成一個個點來建圖,靈活地運用最短路知識
#include<bits/stdc++.h> using namespace std; const int N = 1005; const double INF= 1e10+10; int m, n, vis[N]; double dis[N], mp[N][N]; struct node{ double x, y, r; }cc[1005]; void init() { for (int i=0; i<=n+1; i++) for (int j=0; j<=n+1; j++) { if (i == j) mp[i][j] = 0; else mp[i][j] = INF; } } void creatgraph() { double a, b, c1, c2; scanf("%lf%lf%lf%lf", &a, &b, &c1, &c2); for(int i=1; i<=n; i++) scanf("%lf%lf%lf", &cc[i].x, &cc[i].y, &cc[i].r); mp[0][n+1] = mp[n+1][0] = fabs(c1-c2) / sqrt(a*a+b*b); for(int i=1; i<=n; i++) { double tp = fabs(cc[i].x*a+cc[i].y*b+c1) / sqrt(a*a+b*b) - cc[i].r; if(tp<1e-4) tp=0; mp[0][i] = mp[i][0] = tp; tp = fabs(cc[i].x*a+cc[i].y*b+c2) / sqrt(a*a+b*b) - cc[i].r; if(tp<1e-4) tp=0; mp[n+1][i] = mp[i][n+1] = tp; } for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) { if(i==j) continue; double tp = fabs(cc[i].x-cc[j].x)*fabs(cc[i].x-cc[j].x) + \ fabs(cc[i].y-cc[j].y)*fabs(cc[i].y-cc[j].y); tp = sqrt(tp) - cc[i].r - cc[j].r; if(tp <= 1e-4) tp = 0; mp[i][j] = mp[j][i] = tp; } } void dijkstra(int start) { for (int i=0; i<=n+1; i++) dis[i] = mp[start][i]; memset(vis, 0, sizeof(vis)); vis[start] = 1; for (int i=1; i<=n; i++) { /*找出離起點最近的點*/ double minn = INF; int k = -1; for (int j=0; j<=n+1; j++) { if (!vis[j] && dis[j]<minn) { minn = dis[j]; k = j; } } vis[k] = 1; for (int j=0; j<=n+1; j++) { //鬆弛操作,找到媒介使得出現新的最短路 if (!vis[j] && mp[k][j] < INF) dis[j] = min(dis[j], dis[k] + mp[k][j]); } } } int main() { scanf("%d", &n); //n個頂點 init(); //初始化地圖 creatgraph(); //建圖 dijkstra(0); //核心迪傑斯特拉演算法 printf("%.6f", dis[n+1]); //輸出最短路結果 return 0; }