(2017多校6)1002/hdu-6097 Mindis(计算几何)

来源:互联网 发布:com域名注册局 编辑:程序博客网 时间:2024/06/01 18:04

点我看题

题意:有一个圆心O在原点半径为r的圆,圆上或圆内有两个到圆心距离相等的点P和Q,要求在圆上找到一个点D,使得PD+QD最小。

官方题解:


分析:看了官方题解之后,自己画了图,首先分别作出P和Q的反演点P'和Q'(反演点的一个性质,OP×OQ=r×r),然后判断P'Q'与圆的关系,如果P'Q'与圆相交的话,那么min(PD+QD)就为P'Q'×d/r(其中d为OP的长度,这个是根据相似三角形得到的,一定要画图哇);反之,如果P'Q'与圆相离的话,那么D点就为P'Q'的中垂线与圆心的交点,求出这个交点,就能得到答案(交点的求法:根据比例,PQ中点坐标/中点到圆心距离=交点坐标/半径r)。

参考代码:

#include<cstdio>#include<cmath>#include<cstring>#include<algorithm>#include<iostream>using namespace std;#define eps 1e-8double r;double px,py;//P点double ppx,ppy;//P的反演点double pd;//长度double qx,qy;//Q点double qqx,qqy;//Q的反演点double fx,fy;//反演点的中点double fd;double ans;double ratio;double dist( 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--)    {        scanf("%lf",&r);//半径        scanf("%lf%lf",&px,&py);//p的坐标        scanf("%lf%lf",&qx,&qy);//q的坐标        //求出距离        pd = sqrt(px*px+py*py);//OP和OQ的长度        //这个必须要,防止有的点太小        if( fabs(pd) < eps)        {            printf("%.7f\n",2*r);            continue;        }        //比例        ratio = pd/r;        //求P的反演点        double a;        a = r*r/(pd*pd);        ppx = a*px;        ppy = a*py;        //求Q的反演点        qqx = a*1.0*qx;        qqy = a*1.0*qy;        //反演点的中点        fx = (ppx+qqx)/2;        fy = (ppy+qqy)/2;        //反演点到原点的距离        fd = sqrt(fx*fx+fy*fy);        ans = 0;        if( fd <= r)//有交点,最小距离正比于就为两反演点长度            ans = dist(ppx,ppy,qqx,qqy)*ratio;        else//无交点,找出反演线的中垂线与圆的交点        {            double k = r/fd;            double xx = fx*k;//交点            double yy = fy*k;            ans = 2*sqrt((xx-px)*(xx-px)+(yy-py)*(yy-py));        }        printf("%.7f\n",ans);    }    return 0;}


原创粉丝点击