题目
T(T<=500)组样例,每组样例给出rx,ry,r,x,y(-100<=rx,ry,x,y<=100,0<r<=100)
代表被救的人在(rx,ry-r)位置,且(rx,ry)为圆心有一个半径为r的圆
你从圆外(x,y)出发,题目保证y>ry,
y=ry及这条水平线以下的圆外部分是海,圆内部也是海,都不能经过
问(x,y)到(rx,ry-r)的最短距离
思路来源
归神代码
题解
记A(x,y),O(rx,ry),S(rx,ry-r),D(rx+r,ry),E(rx-r,ry)
过A的直线与圆的切点F,坐标未知
考虑棕色边的三角形AOS,余弦定理求顶角AOS,
余弦定理求直角三角形AFO的角AOF,作差得角FOS
①角FOS小于90度,说明FOS在海里,不可通过直线达,取点E和点D的较近点,再走1/4弧
②角FOS大于90度,FOS可以通过与切点的线段到达,再走圆上一段弧即可
这种判断,省去了对两个切点的分别判断,感觉比较巧妙吖
代码
#include<bits/stdc++.h>
#define db double
using namespace std;
const db pi=acos(-1.0);
const db eps=1e-8;
db dis2(db x,db y,db i,db j)
{
return (x-i)*(x-i)+(y-j)*(y-j);
}
int t;
db rx,ry,r,x,y,ex,ey;
db a,b,arg1,arg2,arg3;
db res;
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%lf%lf%lf%lf%lf",&rx,&ry,&r,&x,&y);
ex=rx;ey=ry-r;
a=dis2(x,y,rx,ry);
b=dis2(x,y,ex,ey);
arg1=acos((a+r*r-b)/(2.0*sqrt(a)*r));
arg2=acos(r/sqrt(a));
arg3=arg1-arg2;
if(arg3<=pi/2+eps)//切点在下半圆周
{
if(x<rx)res=dis2(x,y,rx-r,ry);
else res=dis2(x,y,rx+r,ry);
printf("%.4lf\n",sqrt(res)+pi*r/2.0);
}
else printf("%.4lf\n",sqrt(a-r*r)+arg3*r);
}
return 0;
}