题意:略
思路:今天在大佬哪里get到新知识点,关于圆的反演点,由于画图技能欠缺,这里手动来;
这样就是求圆上一点到A',B'的距离和了,可以发现当线段A'B'与圆相交的时候,最短就是A'B'的值,不想交的时候,就是中垂线与圆的交点到两点距离和了;这里要是不理解,可以想象一下,两点是椭圆的焦点,距离就是2c,就是当椭圆的2c逐渐变大的时候,与圆的第一个切点就是满足的值,很显然,就是中垂线了这点直线的距离就是b;
代码:
#include<cstdio> #include<cstring> #include<cmath> #include<iostream> using namespace std; const double esp=0.000000005; double dis(double x1,double y1,double x2,double y2) { return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); } int main() { int T;scanf("%d",&T); while(T--) { double r,x[2],y[2]; scanf("%lf%lf%lf%lf%lf",&r,&x[0],&y[0],&x[1],&y[1]); double op=dis(0.0,0.0,x[0],y[0]); if(x[0]==x[1]&&y[0]==y[1]){printf("%.7lf ",2.0*(r-op));continue;} if(op==r){printf("%.7lf ",dis(x[0],y[0],x[1],y[1]));continue;} double o=acos((x[0]*x[1]+y[0]*y[1])/op/op)/2.0; double d=r*r/op; double h=d*cos(o); if(h<=r){printf("%.7lf ",2.0*r*sin(o));continue;} double a=h-r,b=d*sin(o); printf("%.7lf ",op*sqrt(a*a+b*b)*2.0/r); } return 0; }