当前位置: 代码迷 >> 综合 >> UVA 12304 2D Geometry 110 in 1! -
  详细解决方案

UVA 12304 2D Geometry 110 in 1! -

热度:46   发布时间:2023-09-23 04:05:12.0

题目地址:https://vjudge.net/problem/UVA-12304

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
#define REP(i,a,b)  for(int i=a;i<=(int)(b);++i)
#define REPD(i,a,b) for(int i=a;i>=(int)(b);--i)
/*Point的模板*/
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 p) { return Vector(A.x*p, A.y*p); }
//向量/数=向量
Vector operator / (Vector A, double p) { return Vector(A.x/p, A.y/p); }bool operator < (const Point& a, const Point& b) {return a.x < b.x || (a.x == b.x && a.y < b.y);
}//比较
const double eps = 1e-4;
int dcmp(double x){if(fabs(x) < eps) return 0;else return x < 0 ? -1: 1;
}bool operator == (const Point& a,const 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 Length(Vector A) { return sqrt(Dot(A,A)); }
double Angle(Vector A, Vector B) { return acos(Dot(A, B))/Length(A)/Length(B); } //两向量的夹角
double Cross(Vector A, Vector B) { return A.x*B.y - A.y*B.x; } //叉积
double Area2(Point A, Point B, Point C) { return Cross(B-A,C-A); } //有向面积//A向量逆时针旋转α rad 
//x'=xcosα-ysinα;
//y'=xsinα+ycosα;
Vector Rotate(Vector A, double rad){return Vector(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));
}//A的单位法线,也就是逆时针90°,长度变为1,注意A要非零向量
Vector Normal(Vector A){ double L=Length(A);return Vector(-A.y/L,A.x/L);
}
/*Point的模板*//*Circle的模板*/
const double PI=acos(-1);
struct Circle
{Point c;double r;Circle(Point c, double r):c(c), r(r) {}Point point(double a) {      //根据极角给出圆上的点return Point(c.x + cos(a)*r, c.y + sin(a)*r);}
};
struct Line
{Point p;  Vector v; //参数方程L=p+v*tLine(Point p,Vector v):p(p),v(v)  {}Point point(double t){     //根据参数方程L=v+(p-v)*t中t求出线上的点return p+(v*t);}
};
//求直线L与圆C的交点,两个交点参数方程值t1,t2,sol保存交点本身,函数返回交点个数
int getLineCircleIntersection(Line L, Circle C, double& t1, double& t2, vector<Point>& sol){double a = L.v.x, b = L.p.x-C.c.x, c = L.v.y, d = L.p.y-C.c.y;double e = a*a+c*c, f = 2*(a*b+c*d), g = b*b+d*d-C.r*C.r;double delta = f*f-4*e*g;if(dcmp(delta) < 0) return 0;if(dcmp(delta) == 0) {t1 = t2 = -f / (2*e) ; sol.push_back(L.point(t1));return 1;}t1 = (-f-sqrt(delta)) / (2*e); sol.push_back(L.point(t1));t2 = (-f+sqrt(delta)) / (2*e); sol.push_back(L.point(t2));return 2;
}
double Angle(Vector v) { return atan2(v.y,v.x); }   //求v的极角
//求圆与圆的交点,函数返回交点数,sol保存交点
int getCircleCircleIntersection(Circle C1, Circle C2, vector<Point>& sol){double d = Length(C1.c-C2.c);if(dcmp(d)==0){if(dcmp(C1.r-C2.r)==0) return -1;  //两圆重合return 0;}if(dcmp(C1.r+C2.r-d)<0) return 0;  //相离if(dcmp(fabs(C1.r-C2.r)-d)>0) return 0;  //内含double a=Angle(C2.c-C1.c);     //求极角double da=acos((C1.r*C1.r+d*d-C2.r*C2.r) / (2*C1.r*d));Point p1=C1.point(a-da), p2=C1.point(a+da);sol.push_back(p1);if(p1==p2) return 1;sol.push_back(p2);return 2;
}
//过点p到圆C做切线,函数返回切线条数,v[i]保存第i条切线的向量
int getTangents(Point p, Circle C, Vector* v){Vector u=C.c-p;double dist=Length(u);if(dist<C.r) return 0;else if(dcmp(dist-C.r)==0) {v[0]=Rotate(u,PI/2);return 1;}else {double ang=asin(C.r/dist);v[0]=Rotate(u, -ang);v[1]=Rotate(u, +ang);return 2;	}
}/*Circle的模板*//*Segment的模板*/
double DistanceToLine(Point P, Point A, Point B){ //P到直线A-B距离Vector v1=B-A, v2=P-A;return fabs(Cross(v1,v2) / Length(v1));
}
Point GetLineIntersection(Point P, Vector v, Point Q, Vector w){  //两直线的交点,前提是Cross(v,w)!=0Vector u=P-Q;double t=Cross(w,u)/Cross(v,w);return P+v*t;
}
/*Segment的模板*/Point p[5];
double r[5];
string s;
vector<Point> ans; 
inline Point ReadPoint(){double a,b;scanf("%lf%lf",&a,&b);return Point(a,b);
}
void CircumscribedCircle(){double x1=p[1].x,x2=p[2].x,x3=p[3].x,y1=p[1].y,y2=p[2].y,y3=p[3].y;  double A1=2*(x2-x1),B1=2*(y2-y1),C1=x2*x2+y2*y2-x1*x1-y1*y1;  double A2=2*(x3-x2),B2=2*(y3-y2),C2=x3*x3+y3*y3-x2*x2-y2*y2;  double x=((C1*B2)-(C2*B1)) / ((A1*B2)-(A2*B1));  double y=((A1*C2)-(A2*C1)) / ((A1*B2)-(A2*B1));  printf("(%.6lf,%.6lf,%.6lf)\n", x,y,Length(Point(x,y)-p[1]));
}
void InscribedCircle(){double a=Length(p[2]-p[3]);double b=Length(p[3]-p[1]);double c=Length(p[1]-p[2]);Point p0=(p[1]*a+p[2]*b+p[3]*c)/(a+b+c);printf("(%.6lf,%.6lf,%.6lf)\n", p0.x,p0.y,DistanceToLine(p0,p[1],p[2]));
}
void TangentLineThroughPoint(){Vector ans[5];int cnt=getTangents(p[2],Circle(p[1],r[1]),ans);double ang[5];REP(i,0,cnt-1){ang[i]=Angle(ans[i])*180/PI;ang[i]=fmod(ang[i]+180,180);}sort(ang,ang+cnt);printf("[");bool first=true;REP(i,0,cnt-1) {if(!first) printf(",");printf("%.6lf", ang[i]);first=false;}printf("]\n");
}
void CircleThroughAPointAndTangentToALineWithRadius(){Point P=p[1],A=p[2],B=p[3]; double rc=r[1];Vector V=B-A,VT=Normal(V)*rc;Line L1=Line(A+VT,V);Line L2=Line(A-VT,V);Circle C=Circle(P,rc);ans.clear();double t1,t2;int cnt=0;cnt+=getLineCircleIntersection(L1,C,t1,t2,ans);cnt+=getLineCircleIntersection(L2,C,t1,t2,ans);sort(ans.begin(), ans.end());printf("[");bool first=true;REP(i,0,cnt-1) {if(!first) printf(",");printf("(%.6lf,%.6lf)", ans[i].x,ans[i].y);first=false;}printf("]\n");
}
void CircleTangentToTwoLinesWithRadius(){Point ans[4];Vector V1=p[2]-p[1],V2=p[4]-p[3];Vector VT1=Normal(V1)*r[1], VT2=Normal(V2)*r[1];ans[0]=GetLineIntersection(p[1]+VT1,V1,p[3]+VT2,V2);ans[1]=GetLineIntersection(p[1]+VT1,V1,p[3]-VT2,V2);ans[2]=GetLineIntersection(p[1]-VT1,V1,p[3]+VT2,V2);ans[3]=GetLineIntersection(p[1]-VT1,V1,p[3]-VT2,V2);sort(ans, ans+4);printf("[");bool first=true;REP(i,0,3) {if(!first) printf(",");printf("(%.6lf,%.6lf)", ans[i].x,ans[i].y);first=false;}printf("]\n");
}
void CircleTangentToTwoDisjointCirclesWithRadius(){Point C0=p[1],C1=p[2];double r0=r[1]+r[3],r1=r[2]+r[3];ans.clear();int cnt=getCircleCircleIntersection(Circle(C0,r0),Circle(C1,r1),ans);sort(ans.begin(), ans.end());printf("[");bool first=true;REP(i,0,cnt-1) {if(!first) printf(",");printf("(%.6lf,%.6lf)", ans[i].x,ans[i].y);first=false;}printf("]\n");
}
void ReadAndSolve(){if(s=="CircumscribedCircle") {REP(i,1,3) p[i]=ReadPoint();CircumscribedCircle();}else if(s=="InscribedCircle"){REP(i,1,3) p[i]=ReadPoint();InscribedCircle();}else if(s=="TangentLineThroughPoint") {p[1]=ReadPoint(); scanf("%lf",&r[1]);p[2]=ReadPoint();TangentLineThroughPoint();}else if(s=="CircleThroughAPointAndTangentToALineWithRadius") {REP(i,1,3) p[i]=ReadPoint();scanf("%lf",&r[1]);CircleThroughAPointAndTangentToALineWithRadius();}else if(s=="CircleTangentToTwoLinesWithRadius"){REP(i,1,4) p[i]=ReadPoint();scanf("%lf",&r[1]);CircleTangentToTwoLinesWithRadius();}else if(s=="CircleTangentToTwoDisjointCirclesWithRadius"){p[1]=ReadPoint(); scanf("%lf",&r[1]);p[2]=ReadPoint(); scanf("%lf",&r[2]);scanf("%lf",&r[3]);CircleTangentToTwoDisjointCirclesWithRadius();}
}int main(int argc, char const *argv[])
{// freopen("input.in","r",stdin);while(cin>>s) ReadAndSolve();return 0;
}


  相关解决方案