牛客國慶集訓派對Day1 L-New Game!(最短路)
阿新 • • 發佈:2019-02-05
時間限制:C/C++ 1秒,其他語言2秒
空間限制:C/C++ 1048576K,其他語言2097152K
Special Judge, 64bit IO Format: %lld
題目描述
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
思路
將第一條線作為起點(第0個點),第二條線作為終點(第n+1個點),第i個圓作為第i個點,這些線與線,線與圓的最短距離作為兩點間的權值進行建圖,然後求最短路就可以了
AC程式碼
//資料好水,這個程式碼有好多樣例都過不去,但是竟然AC了,我以前用的迪傑斯特拉模板不知道為什麼會WA,換成百度找的AC程式碼裡的模板過了。。。好多bug,懶得改了,思路大致就是這樣
#include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> #include <math.h> #include <limits.h> #include <map> #include <stack> #include <queue> #include <vector> #include <set> #include <string> #define ll long long #define ull unsigned long long #define ms(a) memset(a,0,sizeof(a)) #define pi acos(-1.0) #define INF 0x7f7f7f7f #define lson o<<1 #define rson o<<1|1 const double E=exp(1); const int maxn=1e3+10; const int mod=1e9+7; using namespace std; struct wzy { int x,y,r; }p[maxn]; inline double juli(int a,int b,int c,int x,int y) { double _=sqrt(a*1.0*a*1.0+b*1.0*b*1.0); double __=a*1.0*x+b*1.0*y+c*1.0; return fabs(__/_); } inline double juli1(int x,int y,int x1,int y1) { double _=sqrt(fabs(x*1.0-x1*1.0)*fabs(x*1.0-x1*1.0)+fabs(y*1.0-y1*1.0)*fabs(y*1.0-y1*1.0)); return _; } double edge[maxn][maxn]; int flag[maxn]; //flag[i]標記節點i是否被查詢 double dis[maxn]; //dis[i]表示節點i距離起始節點的最短距離 int n,m,a,b,c1,c2; //n個點,m條邊 inline void Dijkstra() { memset(flag,0,sizeof(flag)); for(int i=0;i<=n+1;i++) dis[i]=INF; dis[0]=0; while(1) { int v=-1; for(int i=0;i<=n+1;i++) { if(!flag[i] && (v==-1 || dis[i]<dis[v])) v=i; } if(v==-1)break; flag[v]=1; for(int i=0;i<=n+1;i++) dis[i]=min(dis[i],dis[v]+edge[v][i]); } } int main(int argc, char const *argv[]) { scanf("%d%d%d%d%d",&n,&a,&b,&c1,&c2); for(int i=0;i<maxn;i++) for(int j=0;j<maxn;j++) edge[i][j]=edge[j][i]=INF; for(int i=1;i<=n;i++) scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].r); // 求第一個直線 for(int i=1;i<=n;i++) { double res=juli(a,b,c1,p[i].x,p[i].y)-p[i].r*1.0; if(res<0) edge[0][i]=edge[i][0]=0.0; else edge[0][i]=edge[i][0]=res; } // 求第二個直線 for(int i=1;i<=n;i++) { double res=juli(a,b,c2,p[i].x,p[i].y)-p[i].r*1.0; if(res<0) edge[n+1][i]=edge[i][n+1]=0.0; else edge[n+1][i]=edge[i][n+1]=res; } // 兩圓距離 for(int i=1;i<=n;i++) { for(int j=i+1;j<=n;j++) { double res=juli1(p[i].x,p[i].y,p[j].x,p[j].y)-p[i].r*1.0-p[j].r*1.0; if(res<0) edge[j][i]=edge[i][j]=0.0; else edge[j][i]=edge[i][j]=res; } } Dijkstra(); printf("%.6lf\n",dis[n+1]); return 0; }