题意:求两点之间的最短距离,如果两点穿过圆,则距离是两条切线加一段弧长,图上有。
分析: 用三角形的余弦定理和正弦定理,可以求出相应的一些角度,其实这道题就是一个简单的几何问题,几何会做这道题就会了。
#include <iostream>
#include<cstdio>
#include<cmath>
#include<vector>
#include<list>
#include<cstring>
using namespace std;
#define EPS 1e-8
#define N 1005
int ans[N];
struct point
{
double a,b;
point(){}
point(double a,double b):a(a),b(b){}
point operator +(point p)
{
return point(p.a+a,p.b+b);
}
point operator -(point p)
{
return point(a-p.a,b-p.b);
}
point operator *(double p)
{
return point(a*p,b*p);
}
double dot(point p)//内积
{
return (p.a*a+p.b*b);
}
double det(point p)//外积
{
return (a*p.b-b*p.a);
}
};
struct seg
{
int index;
point p1,p2;
};
point p1,p2;
vector<seg>v;
//判断q是否在线段p1-p2上
bool on_str(point p1,point p2,point q)
{
return (abs((p1-q).det(p2-q))<EPS&&(p1-q).dot(p2-q)<EPS);
}
//求两直线交点
point intersection(point p1,point p2,point q1,point q2)
{
return p1+(p2-p1)*((q2-q1).det(q1-p1)/(q2-q1).det(p2-p1));
}
//两点之间的距离
double dist(point p1,point p2)
{
return sqrt((p1.a-p2.a)*(p1.a-p2.a)+(p1.b-p2.b)*(p1.b-p2.b));
}
//点到直线的距离
double p_seg_dis(point p,point p1,point p2)
{
// A = y1 - y2;
//B = x2 - x1;
//C = x1 * y2 - x2 * y1;
point p3((p1.b-p2.b),(p2.a-p1.a));
// D = fabs(A * x3 + B * y3 + C) / sqrt(A * A + B * B);
// ((p1.b-p2.b)*p.a+(p2.a-p1.a)*p.a)/dis(point())
// cout<<(p.dot(p3)+p1.det(p2))/dist(point(0,0),p3)<<endl;
return fabs((p.dot(p3)+p1.det(p2))/dist(point(0,0),p3));
}
int main()
{
int n;
scanf("%d",&n);
point p1,p2,p(0,0);
while(n--)
{
double r;
scanf("%lf%lf%lf%lf%lf",&p1.a,&p1.b,&p2.a,&p2.b,&r);
if(p_seg_dis(p,p1,p2)>r)
{
printf("%.3f\n",dist(p1,p2));
}
else
{
double ans;
double a=dist(p1,p);
double b=dist(p2,p);
double c=dist(p1,p2);
if((a*a+c*c-b*b)<=0||(b*b+c*c-a*a)<=0)
{
printf("%.3f\n",dist(p1,p2));
continue;
}
ans=sqrt(a*a-r*r)+sqrt(b*b-r*r);
double angle=acos((a*a+b*b-c*c)/(2*a*b))-acos(r/a)-acos(r/b);
ans+=angle*r;
printf("%.3f\n",ans);
}
}
return 0;
}