炫酷双截棍(2019牛客寒假算法基础集训营 Day5-A)

【题目描述】

小希现在手里有一个连着的两块木条,长度分别为l1,l2,木条之间有一个无摩擦的连接点,木条之间可以相互转动,小希将其称之为双截棍。

现在小希把长为l1的木条的一端放在原点(0,0),任意转动这两根木条,小希想知道,是否有可能通过一种转动方式使得双截棍的另一端到达指定点呢?

如果不能,请输出所有能到达的点中离目标点最近的距离。

炫酷双截棍(2019牛客寒假算法基础集训营 Day5-A)

【输入描述】

第一行输入一个两个正整数l1,l2,表示木条长度。

第二行输入一个正整数T,表示询问次数。

随后T行,每行两个实数xi,yi表示目标点的坐标。
l1,l2≤1000
T≤1000
|x|,|y|≤10000

【输出描述】

对于每次询问,如果可以到达,输出0,如果无法到达,给出所有能到达的点中离目标点最近的距离。

你的答案将被认为是正确的,如果相对误差不大于1e-6。

【样例】

示例1

输入
23 13
3
15 1
40 0
0 0
输出
0.00000000
4.00000000
10.00000000

思路:

若只看 l1,可以发现其另一端点的路径是一个圆弧,当在这个圆弧上任一点放 l2 时,可以发现可达的位置是一个圆环,因此,根据两个圆环的关系进行模拟,即可找出离目标点最近的点

由于都是浮点数,因此需要注意一下精度的问题

炫酷双截棍(2019牛客寒假算法基础集训营 Day5-A)

【源代码】

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#define PI acos(-1.0)
#define E 1e-6
#define INF 0x3f3f3f3f
#define N 100001
#define LL long long
const int MOD=1e9+7;
using namespace std;
int main(){
    double l1,l2;
    scanf("%lf%lf",&l1,&l2);
    
    LL t;
    scanf("%lld",&t);
    while(t--){
        double x,y;
        scanf("%lf%lf",&x,&y);
        
        double a=1.0*l1;
        double b=1.0*l2;
        double c=sqrt(1.0*x*x+1.0*y*y);
        
        if(l1>l2){
            if( (c-a+b>=E) && (a+b-c>=E)) 
                printf("0.00000000\n");
            else{
                if(a-b-c>E)
                    printf("%.8lf\n",a-b-c);
                else 
                    printf("%.8lf\n",c-a-b);
            }
        }
        else{
            if(c-b+a>=E&&a+b-c>E)
                printf("0.00000000\n");
            else{
                if(b-a-c>1e-7)
                    printf("%.8lf\n",b-a-c);
                else 
                    printf("%.8lf\n",c-a-b);
            }
        }
    }
    return 0;
}