这道题目由于是射线,所以用直线斜率去做可能会分错方向。首先肯定是要求出四个切点的坐标的。假设这个圆外一点坐标是(a,b),那么可以设另一个点(a+1,b),然后以每个切点分别作第三个点形成夹角。要求这个夹角的角度可以先根据三点求出三边,再套用cosx=(a2+b2-c2)/2ab求出arccosx,这样即可求出四个弧角。最后只要根据这两对弧角判断情况即可(不过分的情况还是蛮多的。。。)
#include <bits/stdc++.h>
using namespace std;
struct POINT{
double x,y;
};
void c2point(POINT p1,double r1,POINT p2,double r2,POINT &rp1,POINT &rp2)
{
double a,b,r;
a=p2.x-p1.x;
b=p2.y-p1.y;
r=(a*a+b*b+r1*r1-r2*r2)/2;
if(a==0&&b!=0)
{
rp1.y=rp2.y=r/b;
rp1.x=sqrt(r1*r1-rp1.y*rp1.y);
rp2.x=-rp1.x;
}
else if(a!=0&&b==0)
{
rp1.x=rp2.x=r/a;
rp1.y=sqrt(r1*r1-rp1.x*rp2.x);
rp2.y=-rp1.y;
}
else if(a!=0&&b!=0)
{
double delta;
delta=b*b*r*r-(a*a+b*b)*(r*r-r1*r1*a*a);
rp1.y=(b*r+sqrt(delta))/(a*a+b*b);
rp2.y=(b*r-sqrt(delta))/(a*a+b*b);
rp1.x=(r-b*rp1.y)/a;
rp2.x=(r-b*rp2.y)/a;
}
rp1.x+=p1.x;
rp1.y+=p1.y;
rp2.x+=p1.x;
rp2.y+=p1.y;
}
//求切点:
// p---圆心坐标, r---圆半径, sp---圆外一点, rp1,rp2---切点坐标
void cutpoint(POINT p,double r,POINT sp,POINT &rp1,POINT &rp2)
{
POINT p2;
p2.x=(p.x+sp.x)/2;
p2.y=(p.y+sp.y)/2;
double dx2,dy2,r2;
dx2=p2.x-p.x;
dy2=p2.y-p.y;
r2=sqrt(dx2*dx2+dy2*dy2);
c2point(p,r,p2,r2,rp1,rp2);
}
int main(){
POINT a,b,c;
double r1,r2;
while(cin>>a.x>>a.y>>b.x>>b.y>>r1>>c.x>>c.y>>r2){
POINT g1,g2,h1,h2;
cutpoint(b,r1,a,g1,g2);
cutpoint(c,r2,a,h1,h2);
double aa,bb,cc;
aa=sqrt((g1.y-a.y)*(g1.y-a.y)+(g1.x-a.x)*(g1.x-a.x));
bb=1;
cc=sqrt((g1.y-a.y)*(g1.y-a.y)+(g1.x-a.x-1)*(g1.x-a.x-1));
double d1=acos((aa*aa+1-cc*cc)/(2*aa));
if(g1.y<a.y) d1=3.1415926535*2-d1; //判在三四象限的情况(因为acos只有0~π)
aa=sqrt((g2.y-a.y)*(g2.y-a.y)+(g2.x-a.x)*(g2.x-a.x));
bb=1;
cc=sqrt((g2.y-a.y)*(g2.y-a.y)+(g2.x-a.x-1)*(g2.x-a.x-1));
double d2=acos((aa*aa+1-cc*cc)/(2*aa));
if(g2.y<a.y) d2=3.1415926535*2-d2;
aa=sqrt((h1.y-a.y)*(h1.y-a.y)+(h1.x-a.x)*(h1.x-a.x));
bb=1;
cc=sqrt((h1.y-a.y)*(h1.y-a.y)+(h1.x-a.x-1)*(h1.x-a.x-1));
double d3=acos((aa*aa+1-cc*cc)/(2*aa));
if(h1.y<a.y) d3=3.1415926535*2-d3;
aa=sqrt((h2.y-a.y)*(h2.y-a.y)+(h2.x-a.x)*(h2.x-a.x));
bb=1;
cc=sqrt((h2.y-a.y)*(h2.y-a.y)+(h2.x-a.x-1)*(h2.x-a.x-1));
double d4=acos((aa*aa+1-cc*cc)/(2*aa));
if(h2.y<a.y) d4=3.1415926535*2-d4;
if(fabs(d2-d1)>3.1415926535){ //判两条射线的夹角是哪一个(大于π的那个肯定不是)
if(d1<d2) d1+=3.14*2;
else d2+=3.14*2;
}
if(fabs(d4-d3)>3.1415926535){
if(d3<d4) d3+=3.14*2;
else d4+=3.14*2;
}
if(d1>3.1415926535*2||d2>3.1415926535*2){ //注意如果某对的一个在2π以上,另一对假如都在一二象限那么也要加2π
if(d3<3.1415926535&&d4<3.1415926535){
d3+=3.1415926535*2;
d4+=3.1415926535*2;
}
}
if(d3>3.1415926535*2||d4>3.1415926535*2){
if(d1<3.1415926535&&d2<3.1415926535){
d1+=3.1415926535*2;
d2+=3.1415926535*2;
}
}
if(min(d1,d2)<=min(d3,d4)&&max(d1,d2)>=max(d3,d4)) cout<<"No"<<endl;
else cout<<"Yes"<<endl;
}
return 0;
}
/*
3 5 5 6 2 8 8 3
No
*/