#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
const double eps=1e-8;
int sgn(double x)
{
if(fabs(x)<eps) return 0;
if(x<0) return -1;
else return 1;
}
struct Point
{
double x;
double y;
Point(){}
Point(double _x,double _y)
{
x=_x;
y=_y;
}
void input()
{
scanf("%lf%lf",&x,&y);
}
bool operator ==(Point b)const
{
return sgn(x-b.x)==0&&sgn(y-b.y)==0;
}
Point operator -(const Point &b)const
{
return Point(x-b.x,y-b.y);
}
double operator ^(const Point &b)const//叉积
{
return x*b.y-y*b.x;
}
double operator *(const Point &b)const//点击
{
return x*b.x-y*b.y;
}
double distance(Point p)//距离
{
return hypot(x-p.x,y-p.y);
}
Point operator *(const double &k)const//数乘
{
return Point(x*k,y*k);
}
};
Point zero(0,0);
double r;
bool judge(Point a,Point b)//判断P1Q1是否与圆相交
{
double oa=zero.distance(a);
double k=r*r/oa/oa;//计算比例
Point ta=a*k;//计算反演点
Point tb=b*k;
double s=fabs(ta^tb);//向量叉积,求三角形面积
double h=s/ta.distance(tb);
if(sgn(h-r)<=0)
return 1;
else
return 0;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%lf",&r);
Point p,q;
p.input();
q.input();
double ans=0;
if(p==q)//两点重合
{
ans=2.0*(r-p.distance(zero));
}
else if(judge(p,q))
{
double op=zero.distance(p);
double k=r*r/op/op;//计算比例
Point tp=p*k;//求反演点
Point tq=q*k;
ans=tp.distance(tq)*op/r;
}
else
{
Point m=Point((p.x+q.x)/2.0,(p.y+q.y)/2.0);//计算中点坐标
double om=zero.distance(m);
double k=r/om;//计算比例
Point td=m*k;//按照比例求D坐标
ans=td.distance(p)+td.distance(q);//直接求DP+DQ
}
printf("%.7lf\n",ans);
}
return 0;
}
HDU6097 Mindis(圆反演点)
最新推荐文章于 2019-12-28 16:47:24 发布