HDU6097(数学题。。。。)

看了题解好久,终于弄懂了,真的是菜。。。。直接上图:
HDU6097(数学题。。。。)_第1张图片
过点P做P的反演点 P1 ,使得 OPOP1=OD2=r2

OPOD=ODOP1=DPDP1

所以只要求出 DP1 的最小值,就可以按比例求出DP。同理求出 DQ1 的最小值,就可以按比例求出DQ。也就是说题目转化成了求 DP1+DQ1 的最小值,两点之间直线最短,连接 P1Q1 ,若与圆相交,则交点即为所求D。若不与圆相交,则PQ中垂线与圆的交点就是D。
判断 P1Q1 与圆的位置关系可以直接算圆心与线段 P1Q1 的距离与半径的大小即可。
code:

#include
#include
#include
#include
#include
#include
#include 
//a&3==a%4
using namespace std;
#define ll long long
#define mem(a) memset(a,0,sizeof(a))
const double eps=1e-8;
const int maxn=30010;//须填写
const int inf=0x3f3f3f3f;

double r,x,y;
double len;


struct Point//可以表示点与向量
{
    double x,y;
    Point()
    {
        x=0;
        y=0;
    }
    Point(double _x,double _y)
    {
        x=_x;
        y=_y;
    }
};
Point zero=Point(0.0,0.0);//(0,0)点

bool judge1(Point a,Point b)//判断两点是否重合
{
    if(a.x==b.x&&a.y==b.y)
        return true;
    else
        return false;
}
double dis(Point a,Point b)//两点间的距离
{
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double chacheng(Point a,Point b)/*两点之间叉乘,用来求三角形OP1Q1的面积,进而求O到P1Q1的距离*/
{
    double res=a.x*b.y-b.x*a.y;
    if(res-0>eps)
    {
        return res;
    }
    else{
        return 0-res;
    }
}
Point shucheng(Point a,double b)//数乘运算,用来求向量OP1,OQ1
{
    Point c=Point(a.x*b,a.y*b);
    return c;
}
bool judge2(Point a,Point b)
{
    double bili=r*r/dis(zero,a)/dis(zero,a);
    Point a1=shucheng(a,bili);
    Point b1=shucheng(b,bili);
    double h=chacheng(a1,b1)/dis(a1,b1);
    if(h-r>eps)
        return false;
    else return true;
}

int main()
{
    int kase;
    scanf("%d",&kase);
    while(kase--)
    {
        scanf("%lf",&r);
        scanf("%lf%lf",&x,&y);
        Point p=Point(x,y);
        scanf("%lf%lf",&x,&y);
        Point q=Point(x,y);

        if(judge1(p,q))//判断两点是否重合
        {
            len=2*(r-dis(q,zero));
        }
        else if(judge2(p,q))//判断P1Q1与圆是否有交点
        {//有的话求出P1Q1,然后按比例求出PQ
            double bili=r*r/dis(zero,p)/dis(zero,p);
            Point p1=shucheng(p,bili);
            Point q1=shucheng(q,bili);
            len=dis(p1,q1)*dis(p,zero)/r;
        }
        else{//没有的话PQ中垂线与圆的交点就是D
            len=0;
            Point mid=Point((p.x+q.x)/2.00,(q.y+p.y)/2.00);
            double bili=r/dis(zero,mid);
            mid=shucheng(mid,bili);
            len=dis(mid,p)+dis(mid,q);
        }
        printf("%.7f\n",len);
    }
    return 0;
}

你可能感兴趣的:(hdu,数学,多校联合)