HDU6097 Mindis

题意:略

思路:今天在大佬哪里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\n",2.0*(r-op));continue;}
        if(op==r){printf("%.7lf\n",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\n",2.0*r*sin(o));continue;}
        double a=h-r,b=d*sin(o);
        printf("%.7lf\n",op*sqrt(a*a+b*b)*2.0/r);
    }
    return 0;
}

 

posted @ 2017-08-11 16:06  MeowMeowMeow  阅读(138)  评论(0编辑  收藏  举报