zoukankan      html  css  js  c++  java
  • 2017ACM暑期多校联合训练

    题目链接

    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

    题意:

    给定一个圆心在坐标原点的圆以及该圆的半径,然后给出两个到该圆的圆心等长的非圆外点(点既可以在圆内,也可以在圆上),让从圆上找一点使其到两点的距离最短。

    分析:

    首先我们考虑两种最特殊的情况:
    1.两个点共位置,这种情况也是完全满足题上给出的条件的,这样的话最短距离就是圆半径减去圆心到改点的距离,因为要看做两个点所以还得乘以2.

    2.两个点在圆上,这样的话最短距离就是两点之间的距离。

    考虑完这两种特殊的情况之后我么看一下一般的情况。

    首先介绍一下反演点的定义:

    如果圆内有一点P,过圆心做一条与P的连线,将这条线延长,使得在圆外的这条线上有一点P',与P关于该圆对称。

    我们即可得出结论OP×OP'=r×r(r为该圆的半径)

    然后我们就可以将求DP+DQ转换为求DP' +DQ',

    现在的问题在于何种情况下这个点都是在中垂线上的这个点吗?

    答案当然不是,我们通过连接两个反演点就可以发现,两个反演点的连线有可能与圆相交,相切的时候可以很简单的确定切点即为所求的点,相离也是如此,问题是相交的时候这个点应该如何确定呢?

    相交的时候P、Q、P'、Q'可以构成一个等腰梯形,梯形与圆有一条腰的平分线,这条平分线就是我们要找的最短的距离,当然梯形与圆的交点不是我们要找的点,我们只是通过等量的转换将它转换过来而已。

    后面在求DP'的长度的时候,应用到一些有关椭圆的知识,P’Q'就是椭圆的长轴,D到椭圆中心的连线即为短半轴,这样的话DP’即为c,可以简单的求得,最终求出答案。

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<iostream>
    using namespace std;
    const double esp=0.000000005;
    double dis(double x1,double y1,double x2,double y2)
    {
        return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
    }
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            double r,x[2],y[2];
            scanf("%lf%lf%lf%lf%lf",&r,&x[0],&y[0],&x[1],&y[1]);
            double op=dis(0.0,0.0,x[0],y[0]);
            if(x[0]==x[1]&&y[0]==y[1])
            {
                printf("%.7lf
    ",2.0*(r-op));
                continue;
            }
            if(op==r)
            {
                printf("%.7lf
    ",dis(x[0],y[0],x[1],y[1]));
                continue;
            }
            double o=acos((x[0]*x[1]+y[0]*y[1])/op/op)/2.0;///op与od的夹角 
            double d=r*r/op;///d表示的是圆心到反演点的距离
            double h=d*cos(o);/// 两反演点构成的直线的距离
            if(h<=r)
            {
                printf("%.7lf
    ",2.0*r*sin(o)); 
                continue;
            }
            double b=h-r,a=d*sin(o);
            printf("%.7lf
    ",op*sqrt(a*a+b*b)*2.0/r);
        }
        return 0;
    }
    
  • 相关阅读:
    [SCOI2012]滑雪与时间胶囊
    [SCOI2012]喵星球上的点名
    SDOI2012 Round1 day2 拯救小云公主(dis)解题报告
    SDOI2012 Round1 day2 象棋(chess)解题报告
    SDOI2012 Round1 day2 集合(set)解题报告
    [Sdoi2014]数数[数位dp+AC自动机]
    [NOI2013]快餐店
    java 日期的格式化 输入/输出
    elastic search 查询语句
    elasticsearch数据迁移——elasticsearch-dump使用
  • 原文地址:https://www.cnblogs.com/cmmdc/p/7348048.html
Copyright © 2011-2022 走看看