B .Battle Royale
题意:给你两个点A,B,以及一个圆S,保证两个点在圆外,且其连线与圆相交,求两点间最短距离。
思路:显然是要分别与圆相切,然后在圆弧想走,直到相交。 那么ans=与圆相交的直线距离+圆弧上的距离; 前者不难求。 后者的话有些抽象,因为不知道怎么取固定角度,但是如果想到atan2了就不难了,因为atan2求出的角度是固定了标准的,注意对用两个atan2求出来的角度求其夹角时,注意不要错过2pi;同时取min(angle,2*pi-angle)。 还不懂的,看代码。
(camp也有类似的题
#include<bits/stdc++.h> using namespace std; const double pi=acos(-1.0); double ans; double dist(double x1,double y1,double x2,double y2){ return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); } pair<double,double> angle(double x1,double y1,double x,double y,double r) { double d=dist(x1,y1,x,y); ans+=(sqrt(d*d-r*r)); double ang1=atan2(y1-y,x1-x); double ang2=acos(r/d); return make_pair(ang1+ang2,ang1-ang2); //返回圆心与切点的角度 } double getlen(double A,double B,double r){ A=fabs(A-B); if(A>=pi*2) A-=pi*2; return r*min(A,pi*2-A); } int main() { double x1,y1,x2,y2,x,y,r; scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); scanf("%lf%lf%lf",&x,&y,&r); scanf("%lf%lf%lf",&x,&y,&r); pair<double,double> A=angle(x1,y1,x,y,r); pair<double,double> B=angle(x2,y2,x,y,r); double Cirlen=getlen(A.first,B.first,r); Cirlen=min(Cirlen,getlen(A.first,B.second,r)); Cirlen=min(Cirlen,getlen(A.second,B.first,r)); Cirlen=min(Cirlen,getlen(A.second,B.second,r)); printf("%.10lf\n",ans+Cirlen); return 0; }