hdu6097—Mindis(计算几何)

题目链接:传送门

Mindis

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1479    Accepted Submission(s): 210
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
T500000
100x,y100
1r100
 

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  106 .
Formally, let your answer be a, and the jury's answer be b. Your answer is considered correct if  |ab|max(1,b)106 .
 

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


题目大意:给出原点O,及P,Q点坐标,且|PO| = |QO|,又给出一个以O为圆心,半径为R的圆C,在圆上任取一点D,使|DO|+|PO|最小。


官方题解:

找出点P关于圆C的反演点P'

那么有三角形DPO与三角形DP'O相似,相似比为|PO|:R

Q点同理

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

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


小丢丢补充:


反演点性质与应用


令|PO| = m,|P'O| = n,有m*n = R*R

|PO|:|DO| = m:R = sqrt(m:n),|DO|:|P'O| = R:n = sqrt(m:n)

所以三角形DPO与三角形DP'O相似


又|DO|:|P'O| = |DO|:|Q'O|,有|P'O| = |Q'O|,所以P'Q'O是等腰三角形,中垂线过O点


当P'Q'与圆C相离,以P',Q'为焦点做椭圆与C相切,切点为P'Q'上垂直平分线与C的交点,即明显此时|DP'|+|DQ'|最小


最后一句——每次都是被大佬们碾压得渣都不剩呀哭


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>

using namespace std;

const double eps = 1e-8;

int sgn(double x)
{
    if(fabs(x)<eps) return 0;
    if(x > 0 ) return 1;
    else return -1;
}

double judge()
{
    double R,x1,y1,x2,y2;
    scanf("%lf%lf%lf%lf%lf",&R,&x1,&y1,&x2,&y2);
    double r = sqrt(x1*x1+y1*y1);

    if(sgn(r) == 0) return 2*R;

    double k = (R*R)/(r*r);
    double x3,y3,x4,y4,mx,my,dis,ans;
    x3 = k*x1;  y3 = k*y1;        //反演点p'
    x4 = k*x2;  y4 = k*y2;        //反演点q'
    mx = (x3+x4)/2;
    my = (y3+y4)/2;
    dis = sqrt(mx*mx+my*my);

    if(sgn(dis-R)<=0){
        ans = sqrt((x4-x3)*(x4-x3)+(y4-y3)*(y4-y3));
    }else{
        ans = 2*sqrt((dis-R)*(dis-R)+(mx-x3)*(mx-x3)+(my-y3)*(my-y3));
    }

    return ans*r/R;
}

int main()
{
    int T;
    scanf("%d",&T);
    while( T-- ){
        printf("%.7lf\n",judge());
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值