WA了无数发。。。
没有仔细看书,漏掉了排序。。。然后还有一些关于精度的错误,那就是少用rotate,后来找到了两个地方的精度错误都是因为用了rotate。。。
然后就没有什么的啦,这就是一道抄模板的题目。
前两个问题可以用公式求,又快又好。
第四个问题要把eps放低才能过样例,1e-6就好,虽然大白书上说不推荐这样做,但是这往往是我们在赛场上的第一反应。
代码
#include<bits/stdc++.h>
using namespace std;
const double PI = acos(-1);
struct Point
{
double x,y;
Point(double x=0,double y=0):x(x),y(y){}
void Print()
{
printf("(%.6lf,%.6lf)",x,y);
}
};
typedef Point Vector;
const double eps = 1e-6;
int dcmp(double x)
{
if(fabs(x)<eps) return 0;
else return x<0?-1:1;
}
Point operator + (Point A,Vector B)
{
return Point(A.x+B.x,A.y+B.y);
}
Vector operator - (Point A,Point B)
{
return Vector(A.x-B.x,A.y-B.y);
}
Vector operator * (Vector A,double t)
{
return Vector(A.x*t,A.y*t);
}
Vector operator / (Vector A,double t)
{
return Vector(A.x/t,A.y/t);
}
bool operator < (Point A,Point B)
{
return A.x<B.x||(A.x==B.x&&A.y<B.y);
}
bool operator == (Point A,Point B)
{
return dcmp(A.x-B.x)==0&&dcmp(A.y-B.y)==0;
}
double Dot(Vector A,Vector B)
{
return A.x*B.x+A.y*B.y;
}
double Cross(Vector A,Vector B)
{
return A.x*B.y-A.y*B.x;
}
double Len(Vector A)
{
return sqrt(Dot(A,A));
}
double Angle(Vector A,Vector B)
{
return acos(Dot(A,B)/Len(A)/Len(B));
}
Point GetInterSection(Point P,Vector v,Point Q,Vector w)
{
Vector u=P-Q;
double t=Cross(w,u)/Cross(v,w);
return P+v*t;
}
Vector Rotate(Vector A,double rad)
{
return Vector(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));
}
double angle(Vector v)
{
return atan2(v.y,v.x);
}
Vector Normal(Vector A)
{
double L=Len(A);
return Vector(-A.y/L,A.x/L);
}
double Dist(Point A,Point B)
{
return Len(A-B);
}
Point MidPoint(Point A,Point B)
{
return Point((A.x+B.x)/2,(A.y+B.y)/2);
}
Point ReadPoint()
{
double x,y;
scanf("%lf %lf",&x,&y);
return Point(x,y);
}
double DistToLine(Point P,Point A,Point B)
{
Vector v1=B-A;
Vector v2=P-A;
return fabs(Cross(v1,v2)/Len(v1));
}
struct Circle
{
Point c;
double r;
Circle(Point c=Point(),double r=0):c(c),r(r){}
Point point(double rad)
{
return Point(c.x+r*cos(rad),c.y+r*sin(rad));
}
};
struct Line
{
Point p;
Vector v;
Line(Point p=Point(),Vector v=Vector()):p(p),v(v){}
Point point(double t)
{
return p+v*t;
}
};
Line ReadLine()
{
Point A=ReadPoint();
Point B=ReadPoint();
Vector V=B-A;
return Line(A,V);
}
Circle ReadCircle()
{
double x,y,r;
scanf("%lf %lf %lf",&x,&y,&r);
return Circle(Point(x,y),r);
}
int GetTangents(Point P,Circle C,Vector *v)
{
Vector u=C.c-P;
double LONG=Len(u);
if(dcmp(LONG-C.r)<0) return 0;
else if(dcmp(LONG-C.r)==0)
{
v[0]=Rotate(u,PI/2);
return 1;
}
else
{
double rad=asin(C.r/LONG);
v[0]=Rotate(u,rad);
v[1]=Rotate(u,-rad);
return 2;
}
}
int GetCircleCircleInterSection(Circle C1,Circle C2,vector<Point>&vec)
{
double d=Dist(C1.c,C2.c);
if(dcmp(d)==0)
{
if(dcmp(C1.r-C2.r)==0) return -1;
else return 0;
}
if(dcmp(C1.r+C2.r-d)<0) return 0;
if(dcmp(fabs(C1.r-C2.r)-d)>0) return 0;
double ang=angle(C2.c-C1.c);
double rad=acos((C1.r*C1.r+d*d-C2.r*C2.r)/(2*C1.r*d));
Point P1=C1.point(ang+rad);
Point P2=C1.point(ang-rad);
vec.push_back(P1);
if(P1==P2) return 1;
vec.push_back(P2);
return 2;
}
int GetLineCircleInterSecontion(Line L,Circle C,double &t1,double &t2,vector<Point>&vec)
{
double a=L.v.x;
double b=L.p.x-C.c.x;
double c=L.v.y;
double d=L.p.y-C.c.y;
double e=a*a+c*c;
double f=2*(a*b+c*d);
double g=b*b+d*d-C.r*C.r;
double delta=f*f-4*e*g;
if(dcmp(delta)<0) return 0;
else if(dcmp(delta)==0)
{
t1=t2=-f/(2*e);
vec.push_back(L.point(t1));
return 1;
}
t1=(-f+sqrt(delta))/(2*e);
t2=(-f-sqrt(delta))/(2*e);
vec.push_back(L.point(t1));
vec.push_back(L.point(t2));
return 2;
}
string s;
void CircumscribedCircle()
{
Point A,B,C;
A=ReadPoint();
B=ReadPoint();
C=ReadPoint();
Vector u=B-A;
Vector v=C-A;
Vector uu=Normal(u);
Vector vv=Normal(v);
Point AB=MidPoint(A,B);
Point AC=MidPoint(A,C);
Point MID=GetInterSection(AB,uu,AC,vv);
double r=Dist(MID,A);
printf("(%.6lf,%.6lf,%.6lf)\n",MID.x,MID.y,r);
}
void InscribedCircle()
{
Point A,B,C;
A=ReadPoint();
B=ReadPoint();
C=ReadPoint();
double a=Dist(B,C);
double b=Dist(A,C);
double c=Dist(A,B);
Point P=Point(A*a+B*b+C*c)/(a+b+c);
Circle CC=Circle(P,DistToLine(P,A,B));
printf("(%.6lf,%.6lf,%.6lf)\n",CC.c.x,CC.c.y,CC.r);
}
void TangentLineThroughPoint()
{
Circle C=ReadCircle();
Point P=ReadPoint();
Vector v[2];
int num=GetTangents(P,C,v);
printf("[");
double ANS[2];
for(int i=0;i<num;i++)
{
double ans=angle(v[i])/PI*180;
while(ans<0) ans+=180;
while(ans>=180) ans-=180;
ANS[i]=ans;
}
sort(ANS,ANS+num);
for(int i=0;i<num;i++)
{
if(i) printf(",");
printf("%.6lf",ANS[i]);
}
puts("]");
}
void CircleThroughAPointAndTangentToALineWithRadius()
{
Circle C;
scanf("%lf %lf",&C.c.x,&C.c.y);
Line L=ReadLine();
scanf("%lf",&C.r);
Vector N=Normal(L.v);
Line L1=Line(L.p+N*C.r,L.v);
Line L2=Line(L.p-N*C.r,L.v);
vector<Point>vec;
double t1,t2;
GetLineCircleInterSecontion(L1,C,t1,t2,vec);
GetLineCircleInterSecontion(L2,C,t1,t2,vec);
printf("[");
sort(vec.begin(),vec.end());
for(unsigned int i=0;i<vec.size();i++)
{
if(i) printf(",");
printf("(%.6lf,%.6lf)",vec[i].x,vec[i].y);
}
puts("]");
}
void CircleTangentToTwoLinesWithRadius()
{
Line L1=ReadLine();
Line L2=ReadLine();
double r;
scanf("%lf",&r);
Vector N1=Normal(L1.v);
Vector N2=Normal(L2.v);
Line L11=Line(L1.p+N1*r,L1.v);
Line L12=Line(L1.p-N1*r,L1.v);
Line L21=Line(L2.p+N2*r,L2.v);
Line L22=Line(L2.p-N2*r,L2.v);
vector<Point>vec;
vec.push_back(GetInterSection(L11.p,L11.v,L21.p,L21.v));
vec.push_back(GetInterSection(L11.p,L11.v,L22.p,L22.v));
vec.push_back(GetInterSection(L12.p,L12.v,L21.p,L21.v));
vec.push_back(GetInterSection(L12.p,L12.v,L22.p,L22.v));
sort(vec.begin(),vec.end());
printf("[");
for(unsigned int i=0;i<vec.size();i++)
{
if(i) printf(",");
vec[i].Print();
}
puts("]");
}
void CircleTangentToTwoDisjointCirclesWithRadius()
{
Circle C1=ReadCircle();
Circle C2=ReadCircle();
double r;
scanf("%lf",&r);
C1.r+=r;
C2.r+=r;
vector<Point>vec;
GetCircleCircleInterSection(C1,C2,vec);
printf("[");
sort(vec.begin(),vec.end());
for(unsigned int i=0;i<vec.size();i++)
{
if(i) printf(",");
vec[i].Print();
}
puts("]");
}
int main()
{
//freopen("data.txt","r",stdin);
while(cin>>s)
{
if(s=="CircumscribedCircle") CircumscribedCircle();
else if(s=="InscribedCircle") InscribedCircle();
else if(s=="TangentLineThroughPoint") TangentLineThroughPoint();
else if(s=="CircleThroughAPointAndTangentToALineWithRadius") CircleThroughAPointAndTangentToALineWithRadius();
else if(s=="CircleTangentToTwoLinesWithRadius") CircleTangentToTwoLinesWithRadius();
else if(s=="CircleTangentToTwoDisjointCirclesWithRadius") CircleTangentToTwoDisjointCirclesWithRadius();
}
return 0;
}