CSU 1503 点到圆弧的距离(最易理解)

第一步找出圆心

根据题目给出的三点建立两条直线,两直线垂直平分线的交点就是圆心

第二步判断点与圆弧的位置关系

通过分析,可分为两种情况;

情况一,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;
}

 

转载于:https://www.cnblogs.com/zhizhaozhuo/p/9594213.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值