炫酷双截棍(2019牛客寒假算法基础集训营 Day5-A)
【题目描述】
小希现在手里有一个连着的两块木条,长度分别为l1,l2,木条之间有一个无摩擦的连接点,木条之间可以相互转动,小希将其称之为双截棍。
现在小希把长为l1的木条的一端放在原点(0,0),任意转动这两根木条,小希想知道,是否有可能通过一种转动方式使得双截棍的另一端到达指定点呢?
如果不能,请输出所有能到达的点中离目标点最近的距离。
【输入描述】
第一行输入一个两个正整数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 时,可以发现可达的位置是一个圆环,因此,根据两个圆环的关系进行模拟,即可找出离目标点最近的点
由于都是浮点数,因此需要注意一下精度的问题
【源代码】
#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;
}