CSU 1503 点到圆弧的距离(最易理解)
程序员文章站
2022-07-14 19:28:28
...
第一步找出圆心
根据题目给出的三点建立两条直线,两直线垂直平分线的交点就是圆心
第二步判断点与圆弧的位置关系
通过分析,可分为两种情况;
情况一,ans1为p到p1的距离减去圆的半径的绝对值
情况二,ans2为p到A,C两点的距离最小值
给出f1,f2,f3,f4分别表示向量 p1A, p1B,p1C,p1P与x正半轴的夹角;
考虑到没有给出给点的顺序,有可能顺时针或逆时针给点。
给出判断的代码:
if(f1<f3){
if((f2<=f3&&f2>=f1) == (f4<=f3&&f4>=f1))ans=ans1;
else ans=ans2;
}else{
if((f2>=f3&&f2<=f1) == (f4>=f3&&f4<=f1))ans=ans1;
else ans=ans2;
}
下面分析这段代码:
f1<f3时,表示A,C的位置关系
顺时针给点会形成如下的圆弧;
显然f2 不会满足 f2<=f3&&f2>=f1 如果 f4也不满足 f4<=f3&&f4>=f1,即(f2<=f3&&f2>=f1) == (f4<=f3&&f4>=f1)
则答案是ans1;
如果f4满足 f4<=f3&&f4>=f1 即(f2<=f3&&f2>=f1) != (f4<=f3&&f4>=f1)
则答案是ans2;
逆时针给点会形成如下的圆弧;
显然f2 满足 f2<=f3&&f2>=f1如果 f4也满足 f4<=f3&&f4>=f1,即(f2<=f3&&f2>=f1) == (f4<=f3&&f4>=f1)
则答案是ans1;
如果f4不满足 f4<=f3&&f4>=f1 即(f2<=f3&&f2>=f1) != (f4<=f3&&f4>=f1)
则答案是ans2;
f1>=f3时的情况按照上面的步骤分析一下即可
完整代码:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
struct Point{
double x,y;
Point(double x=0,double y=0):x(x),y(y){}
};
typedef Point Vector;
Vector operator + (Vector A,Vector B){return Vector(A.x+B.x,A.y+B.y);}
Vector operator - (Vector A,Vector B){return Vector(A.x-B.x,A.y-B.y);}
Vector operator * (Vector A,double B){return Vector(A.x*B,A.y*B);}
Vector operator / (Vector A,double B){return Vector(A.x/B,A.y/B);}
double Dot(Vector A,Vector B){return A.x*B.x+A.y*B.y;}
double Length(Vector A){return sqrt(Dot(A,A));}
double Cross(Vector A,Vector B){return A.x*B.y-B.x*A.y;}
Vector Normal(Vector A){
double l=Length(A);
return Vector(-(A.y/l),A.x/l);
}
Point GetLineIntersection(Point P,Vector v,Point Q,Vector w){
Vector u=P-Q;
double t=Cross(w,u)/Cross(v,w);
return P+v*t;
}
double Distance(Point a,Point b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
int main(){
Point a,b,c,p,p1;
int Case=0;
while(~scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&a.x,&a.y,&b.x,&b.y,&c.x,&c.y,&p.x,&p.y)){
Point mid1,mid2;
mid1.x=(a.x+b.x)/2;mid1.y=(a.y+b.y)/2;
mid2.x=(a.x+c.x)/2;mid2.y=(a.y+c.y)/2;
Vector v1=(b-a);
Vector v2=(c-a);
v1=Normal(v1);
v2=Normal(v2);
p1=GetLineIntersection(mid1,v1,mid2,v2);//通过三点建立两直线,两直线的垂直平分线交点就是圆心
double ans,ans1,ans2;
double da,dc,dp1,r;
dp1=Distance(p,p1);
r=Distance(p1,a);
da=Distance(p,a);
dc=Distance(p,c);
ans1=fabs(dp1-r);
ans2=min(da,dc);
double f1=atan2(a.y-p1.y,a.x-p1.x);
double f2=atan2(b.y-p1.y,b.x-p1.x);
double f3=atan2(c.y-p1.y,c.x-p1.x);
double f4=atan2(p.y-p1.y,p.x-p1.x);
if(f1<f3){
if((f2<=f3&&f2>=f1) == (f4<=f3&&f4>=f1))ans=ans1;
else ans=ans2;
}else{
if((f2>=f3&&f2<=f1) == (f4>=f3&&f4<=f1))ans=ans1;
else ans=ans2;
}
printf("Case %d: %.3lf\n",++Case,ans);
}
return 0;
}
上一篇: 线性回归小测试
下一篇: 点到线段的距离 计算几何