牛客國慶集訓派對Day1 L New Game!
阿新 • • 發佈:2019-02-13
這個題是一個最短路的練習;
我們將每一個圓心看成一個連線點,將他們的路徑連線起來,求距離的時候需要注意(在圓內,圓上,線上它們的距離是0)
當兩個圓相離它們的距離就是兩點之間的距離減去兩點的半徑,如果是一個負值說明兩個圓是相交的,那麼它們的距離就是0;
剩下的就是一個spfa解決這個問題;
程式碼如下:
#include <bits/stdc++.h> #define maxn 100005 typedef long long ll; using namespace std; struct cir { double x; double y; double r; } mapp[maxn]; struct node { ll xx; double step; node(ll xxx,double yy):xx(xxx),step(yy){} }; bool operator <(const node a,const node b) { return a.step > b.step; } ll n; vector<pair<ll,double> >p[maxn]; priority_queue<node>q; double dis[maxn]; ll flag[maxn]; void spfa() { for(int i = 1; i <= n + 1; i ++) dis[i]=2147483647; dis[0] = 0; q.push(node(0,0.0)); while(!q.empty()) { node kk = q.top(); q.pop(); flag[kk.xx] = 1; if(kk.step != dis[kk.xx])continue; for(int i = 0; i < p[kk.xx].size(); i ++) { ll to = p[kk.xx][i].first; if(!flag[to] && dis[to] > dis[kk.xx] + p[kk.xx][i].second) { dis[to] = dis[kk.xx] + p[kk.xx][i].second; q.push(node(to,dis[to])); } } } } int main() { double a,b,c1,c2,tep; cin >> n >> a >> b >> c1 >> c2; for(int i = 1; i <= n; i ++) { cin >> mapp[i].x >> mapp[i].y >> mapp[i].r; tep = max(fabs((a * mapp[i].x + b * mapp[i].y + c1) / sqrt(a * a + b * b)) - mapp[i].r,0.0); p[0].push_back(make_pair(i,tep)); p[i].push_back(make_pair(0,tep)); tep = max(fabs((a * mapp[i].x + b * mapp[i].y + c2) / sqrt(a * a + b * b)) - mapp[i].r,0.0); p[n+1].push_back(make_pair(i,tep)); p[i].push_back(make_pair(n+1,tep)); } for(int i = 1; i <= n; i ++) { for(int j = i + 1; j <= n; j ++) { tep = max(sqrt((mapp[i].x - mapp[j].x) * (mapp[i].x - mapp[j].x) + (mapp[i].y - mapp[j].y) * (mapp[i].y - mapp[j].y)) - mapp[i].r - mapp[j].r,0.0); p[i].push_back(make_pair(j,tep)); p[j].push_back(make_pair(i,tep)); } } spfa(); cout << fixed << setprecision(6) << dis[n+1] << endl; return 0; }