HDU 6097 Mindis(几何)

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;
}







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值