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;
}
View Code

相关文章: