Mindis(hdu6097)

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

给一个圆C和圆心O,P、Q是圆上或圆内到圆心距离相等的两个点,在圆上取一点D,求|PD| + |QD|的最小值

做点P、Q的反演点P'、Q', |OP| * |OP'| = r ^ 2, |OQ| * |OQ'| = r ^ 2.

|OP| / r = r / |OP'|, 即|OP| / |OD| = |OD| / |OP'|, 所以△OPD ∽ △ODP', 同理, △OQD ∽ △ODQ', 相似比为|OP| / r.

所以, |PD| + |QD| = (|P'D| + |Q'D|) * |OP| / r. 转化为求|P'D| + |Q'D|的最小值

若P'Q'与圆C有交点,则|P'D| + |Q'D|的最小值为|P'Q'| (此时D为P'Q'与圆C的交点, |P'D| + |Q'D| 为直线,值最小)

若P'Q'与圆C无交点,则D为PQ的中垂线与圆C的交点时, |P'D| + |Q'D|取得最小值(以P、Q为焦点做椭圆,令椭圆不断变大,椭圆与圆C有一个交点时,此交点即为点D)

这道题要用比例做 ,要用斜率找点很麻烦,有斜率等于0 或者没有斜率的情况

#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
const double eps=1e-8;
struct point
{
    double x,y;
}p,q;
double len(point a,point c)
{
    return sqrt((a.x-c.x)*(a.x-c.x)+(a.y-c.y)*(a.y-c.y));
}
int main()
{
    int T;
    double r;
    scanf("%d", &T);
    while (T-- )
    {
        scanf("%lf",&r);
        scanf("%lf%lf",&p.x,&p.y);
        scanf("%lf%lf",&q.x,&q.y);
        point o;
        o.x=0.0;
        o.y=0.0;
        double op=len(p,o);
        point pp,qq,d;
        if(abs(op)<=eps)
        {
            printf("%.6lf\n",r*2);
        }
        else
        {
            double l=r*r/op;
            pp.x=p.x*l/op;
            pp.y=p.y*l/op;
            qq.x=q.x*l/op;
            qq.y=q.y*l/op;
            d.x=(pp.x+qq.x)/2;
            d.y=(pp.y+qq.y)/2;
            if(len(o,d)<=r)
            {
                double ans=len(pp,qq)*op/r;
                printf("%.6lf\n",ans);
            }
            else
            {
                double dis=len(o,d);
                double t=r/dis;
                d.x=d.x*t;
                d.y=d.y*t;
                double ans=2*len(d,p);
                printf("%.6lf\n",ans);
            }
        }
    }

    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值