UVA 12304 2D Geometry 110 in 1! -

来源:互联网 发布:软件质量管理 编辑:程序博客网 时间:2024/05/17 09:02

题目地址: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;}


0 0
原创粉丝点击