HDU6097Mindis(圆反演点)

来源:互联网 发布:优化一个关键词多少钱 编辑:程序博客网 时间:2024/06/13 07:48

这里写图片描述

#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;}
原创粉丝点击