Wannafly summer camp Day2 ——9519: New Game(最短路dijktra)
9519: New Game
時間限制: 1 Sec 記憶體限制: 128 MB Special Judge 提交: 175 解決: 64 [提交] [狀態] [討論版] [命題人:admin]
題目描述
Eagle Jump公司正在開發一款新的遊戲。瀧本一二三作為其員工,獲得了提前試玩的機會。現在她正在試圖通過一個迷宮。 這個迷宮有一些特點。為了方便描述,我們對這個迷宮建立平面直角座標系。迷宮中有兩條平行直線 L1:Ax+By+C1=0,L2:Ax+By+C2=0,還有 n 個圓 。角色在直線上、圓上、圓內行走不消耗體力。在其他位置上由S點走到T點消耗的體力為S和T的歐幾里得距離。 瀧本一二三想從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即算正確。
樣例輸入
2 0 1 0 -4
0 1 1
1 3 1
樣例輸出
0.236068
來源/分類
解題思路:把兩條平行線當做兩個點0和n+1,與其他n個圓一起構建(n+2)*(n+2)無向圖。從0開始跑最短路就好啦。建圖有點繁瑣....
AC程式碼:
#include<bits/stdc++.h> #define rep(i,j,k) for(int i=j;i<k;i++) #define per(i,j,k) for(int i=j;i<=k;i++) #define IO std::ios::sync_with_stdio(false),cin.tie(NULL),cout.tie(NULL); using namespace std; typedef long long ll; const int maxn = 1005; const double INF = 1e6+7; const double eps = 1e-4; struct node { double dis; int nod; node(){} node(double dis,int nod): dis(dis),nod(nod){}; bool operator < (const node &a) const{ return dis>a.dis; //變更大小邏輯 } }; struct circle{ double x; double y; double r; }crl[maxn];
double maps[maxn][maxn]; double d[maxn]; int vis[maxn]; int n; double a,b,c1,c2;
void add(int i,int j) { //圓到圓的距離 double len = sqrt( (crl[i].x-crl[j].x)*(crl[i].x-crl[j].x) + (crl[i].y-crl[j].y)*(crl[i].y-crl[j].y) ); len -= (crl[i].r+crl[j].r); if(len<=eps) len = 0; maps[i][j] = maps[j][i] = len; } void make_graph() { fill(maps[0],maps[0]+1005*1005,INF); per(i,1,n) per(j,i+1,n) add(i,j); per(i,1,n) //圓心到兩條直線的距離 { double len1 = fabs(a*crl[i].x + b*crl[i].y + c1)/sqrt(a*a+b*b) - crl[i].r; double len2 = fabs(a*crl[i].x + b*crl[i].y + c2)/sqrt(a*a+b*b) - crl[i].r; maps[i][0] = maps[0][i] = (len1<0? 0:len1); maps[i][n+1] = maps[n+1][i] = (len2<0? 0:len2); } maps[0][n+1] = maps[n+1][0] = fabs(c1-c2)/sqrt(a*a+b*b); }
void dijkstra() //dijkstra 的佇列優化演算法 { memset(vis,0,sizeof(vis)); fill(d,d+n+2,INF); //非0 1 用fill更快哦~ priority_queue <node> q; q.push(node(0.0,0)); //以上邊為起點,初始到自己的距離為0; d[0] = 0.0; while(!q.empty()) { int cur = q.top().nod; q.pop(); if(vis[cur]) continue; vis[cur] = 1; per(i,0,n+1) { if(!vis[i] && d[i]>d[cur]+maps[cur][i]) { d[i] = d[cur] + maps[cur][i]; q.push(node(d[i],i)); } } } }
void spfa(int from,int to) // Bellman-Ford演算法 的佇列優化演算法,可用於負邊權圖 { memset(vis,0,sizeof vis); fill(d,d+n+2,INF); queue<int> q; q.push(from); vis[from]=true; d[from]=0; while(!q.empty()){ int cur=q.front(); q.pop(); vis[cur]=false; for(int i=0;i<=n+1;i++) { if(d[i]>d[cur]+maps[cur][i]) { d[i]=d[cur]+maps[cur][i]; if(!vis[i]) { vis[i]=true; q.push(i); } } } } }
//#define LOCAL int main(void) { #ifdef LOCAL freopen("in.txt","r",stdin); #endif IO cin>>n>>a>>b>>c1>>c2; per(i,1,n) cin>>crl[i].x>>crl[i].y>>crl[i].r; make_graph(); dijkstra(); //spfa(0,n+1); cout<<setiosflags(ios::fixed)<<setprecision(6)<<d[n+1]<<endl; }
/************************************************************** dijkstra() Language: C++ Result: 正確 Time:24 ms Memory:10160 kb ****************************************************************/ /************************************************************** spfa() Language: C++ Result: 正確 Time:68 ms Memory:9648 kb ****************************************************************/