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
44
4 0
0 4
4
0 3
3 0
4
0 2
2 0
4
0 1
1 0
Sample Output
5.65685435.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;
}