这个题是一个最短路的练习;
我们将每一个圆心看成一个连接点,将他们的路径连接起来,求距离的时候需要注意(在圆内,圆上,线上它们的距离是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;
}