hdu 6097 Mindis(数学几何,圆心的反演点)

Mindis

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 2787    Accepted Submission(s): 555
Special Judge

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
Recommend
liuyiding   |   We have carefully selected several similar problems for you:  6119 6118 6117 6116 6115 
 
以下转自:http://blog.csdn.net/kkkkahlua/article/details/77074409

题意:

圆心 O 坐标(0, 0), 给定两点 P, Q(不在圆外),满足 PO = QO,

要在圆上找一点 D,使得 PD + QD 取到最小值。

 

官方题解:

做P点关于圆的反演点P',OPD与ODP'相似,相似比是|OP| : r。

Q点同理。

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

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

时间复杂度 O(1)O(1)

补充说明:

反演:

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

在这里,k 即为圆半径 r ^ 2,因此,相似就是显然的了。

 

当 P'Q' 与圆有交点时:

不妨设交点为 O',若 D 不为 O',则 P'D + Q'D >  P'Q'(三角形两边之和大于第三边);当且仅当 D 取 O' 时,P'Q + Q'D 取到最小值,即为 P'Q'。

当 P'Q' 与圆无交点时:

不妨将 P' 与 Q' 看成椭圆的两个焦点,当椭圆慢慢变大时,第一个碰到的圆上的点 D 即为使得 P'D + Q'D 最小的点;画个图就很显然了,第一个碰到的点即为 PQ 的中垂线与圆的交点。

 

至于判断有 P'Q' 与圆有没有交点,就是圆心到直线的距离与半径比较,又因为此处 P'O=Q'O,所以只需要比较 P'Q' 的中点到圆心的距离和半径的大小。

 

注意点:

1. 注意 PO = QO = 0 的情况

2. 尽量用比例而不是角度进行计算

 
这题精度很是问题
#include <iostream>
#include<bits/stdc++.h>
using namespace std;

const double eps=1e-8;
int t;
double R,px,py,qx,qy;
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%lf%lf%lf%lf%lf",&R,&px,&py,&qx,&qy);
        if (px==0 && py==0) {printf("%.7lf\n",2*R);continue;}
        double r=sqrt(pow(px,2)+pow(py,2));
        double k=R*R/(r*r);  //不是相似比
        double ppx=px*k,ppy=py*k,qqx=qx*k,qqy=qy*k;
        //printf("%.2lf %.2lf\n",ppx,ppy);
        double midx=(ppx+qqx)/2,midy=(ppy+qqy)/2;
        double dis=sqrt(pow(midx,2)+pow(midy,2) );
        //printf("%.7lf\n",dis);
        if (dis<=R)
        {
           // double op2=sqrt(pow(ppx,2)+pow(ppy,2));
            printf("%.7lf\n",sqrt(pow(ppx-qqx,2)+pow(ppy-qqy,2))*r/R);

        } else
        {
            double mx=midx/dis*R; double my=midy/dis*R;
            printf("%.7lf\n",2*sqrt(pow(mx-px,2)+pow(my-py,2)) );
        }
    }
    return 0;
}

 

posted on 2017-08-14 12:28  Yxter  阅读(464)  评论(0)    收藏  举报

导航