1. 程式人生 > >Wannafly summer camp Day2 ——9519: New Game(最短路dijktra)

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 ****************************************************************/