HDU 6097 Mindis(几何)

来源:互联网 发布:数据库系统特点 编辑:程序博客网 时间:2024/06/02 13:12

Mindis

Problem Description

The center coordinate of the circle C is O, the coordinate of O is (0,0) , and the radius is r.
P and Q are two points not outside the circle, and PO = QO.
You need to find a point D on the circle, which makes PD+QD minimum.
Output minimum distance sum.



Input

The first line of the input gives the number of test cases T; T test cases follow.
Each case begins with one line with r : the radius of the circle C.
Next two line each line contains two integers x , y denotes the coordinate of P and Q.

Limits
T≤500000
−100≤x,y≤100
1≤r≤100



Output

For each case output one line denotes the answer.
The answer will be checked correct if its absolute or relative error doesn't exceed 10−6.
Formally, let your answer be a, and the jury's answer be b. Your answer is considered correct if |a−b|max(1,b)≤10−6.



Sample Input

4
4
4 0
0 4
4
0 3
3 0
4
0 2
2 0
4
0 1
1 0



Sample Output

5.6568543
5.6568543
5.8945030

6.7359174

Source

2017 Multi-University Training Contest - Team 6


题意:圆心为O(0,0),给出圆的半径以及不在圆外的两点P、Q坐标,且OP=OQ,求圆上一点D,使PD+QD最小。


题解:做P点关于圆的反演点P'(OP*OP'=r*r),OPD与ODP'相似,相似比是|OP| : r。Q点同理。

极小化PD+QD可以转化为极小化P'D+Q'D。

当P'Q'与圆有交点时,答案为两点距离,否则最优值在中垂线上取到。

反演变换:设在平面内给定一点O和常数k(k不等于零),对于平面内任意一点A,确定A′,使A′在直线OA上一点,并且有向线段OA与OA′满足OA·OA′=k,我们称这种变换是以O为的反演中心,以k为反演幂的反演变换,简称反演。称A′为A关于O(r)的互为反演点.

#include<iostream>#include<stdio.h>#include<string.h>#include<algorithm>#include<vector>#include<queue>#include<stack>#include<math.h>#define ll long long#define INF 5e9;using namespace std;int main(){    int t;    scanf("%d",&t);    while(t--)    {        double x1,y1,x2,y2,r;        scanf("%lf",&r);        scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);        if(x1==x2&&y1==y2)        {            double s=r-sqrt(x1*x1+y1*y1);            printf("%.7f\n",2*s);            continue;        }        double a=((x2-x1)*1.0)/(y1-y2);//中垂线斜率        double x=sqrt((r*r)/(a*a+1));        double y=sqrt(r*r-x*x);//交点坐标        if(a<0) y=-y;        double res1=sqrt((x1-x)*(x1-x)+(y1-y)*(y1-y))+sqrt((x2-x)*(x2-x)+(y2-y)*(y2-y));        x=-x;        y=-y;        double res2=sqrt((x1-x)*(x1-x)+(y1-y)*(y1-y))+sqrt((x2-x)*(x2-x)+(y2-y)*(y2-y));        if(y1==y2)//单独判断斜率无穷大的情况        {            res1=sqrt(x1*x1+(y1-r)*(y1-r))+sqrt(x2*x2+(y2-r)*(y2-r));            res2=sqrt(x1*x1+(y1+r)*(y1+r))+sqrt(x2*x2+(y2+r)*(y2+r));        }        double res=0;        if(res1>res2) res=res2;        else res=res1;        double x3=0,x4=0,y3=0,y4=0;        double p=(r*r)/(x1*x1+y1*y1);         x3=x1*p;//P'坐标         y3=y1*p;         x4=x2*p;//Q'坐标         y4=y2*p;        double xx=(x3+x4)/2;        double yy=(y3+y4)/2;        double d=xx*xx+yy*yy;        if(d<=r*r)//判断P'Q'是否与圆有交点          {              res=(sqrt((x3-x4)*(x3-x4)+(y3-y4)*(y3-y4)));              res/=sqrt(p);          }        printf("%.7f\n",res);    }    return  0;}







原创粉丝点击