The 2019 ACM-ICPC China Shannxi Provincial Programming Contest C.Angel's Journey(计算几何基础)

题目

T(T<=500)组样例,每组样例给出rx,ry,r,x,y(-100<=rx,ry,x,y<=100,0

代表被救的人在(rx,ry-r)位置,且(rx,ry)为圆心有一个半径为r的圆

你从圆外(x,y)出发,题目保证y>ry,

y=ry及这条水平线以下的圆外部分是海,圆内部也是海,都不能经过

问(x,y)到(rx,ry-r)的最短距离

思路来源

归神代码

题解

The 2019 ACM-ICPC China Shannxi Provincial Programming Contest C.Angel's Journey(计算几何基础)_第1张图片

记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
#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

 

你可能感兴趣的:(计算几何)