头文件
/*author:revolIA*/ /* 492 357 816 */ #include#define max(a,b) (a>b?a:b) #define min(a,b) (ausing namespace std; typedef long long ll; const int maxn = 1e3+7; const double esp = 1e-6,pi = acos(-1); double o2(double x){return x*x;} //点 int dcmp(double x){ if(fabs(x) return 0; return x<0?-1:1; } struct Point{ double x,y; void read(){scanf("%lf%lf",&x,&y);} Point(double x = 0,double y = 0):x(x),y(y){} }; double Cross(const Point A,const Point B){ return A.x*B.y-A.y*B.x; } double Dot(const Point A,const Point B){ return A.x*B.x+A.y*B.y; } double Len(const Point A){ return sqrt(Dot(A,A)); } double Angle(const Point A,const Point B){ return acos(Dot(A,B)/Len(A)/Len(B)); } Point operator + (const Point A,const Point B){ return Point(A.x+B.x,A.y+B.y); } Point operator - (const Point A,const Point B){ return Point(A.x-B.x,A.y-B.y); } Point operator * (const Point A,const double B){ return Point(A.x*B,A.y*B); } Point operator / (const Point A,const double B){ return Point(A.x/B,A.y/B); } Point Rotate(const Point A,double rad){return Point(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));} //负数表示顺时针 Point Normal(const Point A){return Point(-A.y/Len(A),A.x/Len(A));}//法向量 bool operator == (const Point A,const Point B){return !dcmp(A.x-B.x)&&!dcmp(A.y-B.y); } bool operator != (const Point A,const Point B){return !(A == B);} bool operator < (const Point A,const Point B){return dcmp(A.x-B.x)<0 || (!dcmp(A.x-B.x)&&dcmp(A.y-B.y)<0);} typedef Point Vector; bool quickRepel(Point x1,Point y1,Point x2,Point y2){//快速排斥 Point Lx = Point(min(x1.x,y1.x),min(x1.y,y1.y)); Point Rx = Point(max(x1.x,y1.x),max(x1.y,y1.y)); Point Ly = Point(min(x2.x,y2.x),min(x2.y,y2.y)); Point Ry = Point(max(x2.x,y2.x),max(x2.y,y2.y)); Point L = Point(max(Lx.x,Ly.x),max(Lx.y,Ly.y)); Point R = Point(min(Rx.x,Ry.x),min(Rx.y,Ry.y)); return (L.x<=R.x) && (L.y<=R.y); } bool OnSegment(Point P,Point x,Point y){//点在线段上 if(P == x||P == y)return 1; return !dcmp(Cross(x-P,y-P))&&dcmp(Dot(P-x,P-y))<0; } bool straddle(Point x1,Point y1,Point x2,Point y2){//跨立实验(线段是否有交点) if(!quickRepel(x1,y1,x2,y2))return 0; double c1 = Cross(y1-x1,x2-x1),c2 = Cross(y1-x1,y2-x1); double c3 = Cross(y2-x2,x1-x2),c4 = Cross(y2-x2,y1-x2); return dcmp(c1)*dcmp(c2)<=0 && dcmp(c3)*dcmp(c4)<=0; //允许部分重合或在端点重合 //return dcmp(c1)*dcmp(c2)<0 && dcmp(c3)*dcmp(c4)<0; //必须只有一个交点且不在端点上 } Point LinearIntersection(Point P,Vector v,Point Q,Vector w){//解直线交点 assert(v != w);//Parallel 平行线 Vector u = P-Q; double t = Cross(w,u)/Cross(v,w); return P+v*t; } Point GetLineProjection(Point P,Point A,Point B){//P投影到AB上的点 Vector v = B-A; return A+v*(Dot(v,P-A)/Dot(v,v)); } Point SymmetricPoint(Point P,Point A,Point B){//P关于AB的对称点 return GetLineProjection(P,A,B)*2.0-P; } double DistanceToline(Point P,Point A,Point B){//点到直线距离 Vector v1 = B-A,v2 = P-A; return fabs(Cross(v1,v2))/Len(v1); } double DistanceToSegment(Point P,Point A,Point B){//点到线段距离 if(A == B)return Len(P-A); Vector v1 = B-A,v2 = P-A,v3 = P-B; if(dcmp(Dot(v1,v2))<0)return Len(v2); if(dcmp(Dot(v1,v3))>0)return Len(v3); return fabs(Cross(v1,v2))/Len(v1); } //直线 struct Line{ Point p; Vector v; double ang; Line(){} Line(Point p,Vector v):p(p),v(v){ang = atan2(v.y,v.x);} Point point(double t){ return p+v*t; } bool operator < (const Line& T)const{ return ang<T.ang; } }; //圆 struct Circle{ Point c; double r; Circle(){} Circle(Point c,double r):c(c),r(r){} void read(){ c.read(); scanf("%lf",&r); } Point point(double a){return Point(c.x+cos(a)*r,c.y+sin(a)*r);} }; //圆和直线交点 int getLineCircleIntersection(Line L,Circle C,double& t1,double& t2,vector & 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);} //圆和圆的交点 int getCircleCircleIntersection(Circle C1,Circle C2,vector & sol){ double d = Len(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; } //过定点求圆切线 int getTangents(Point p,Circle C,Vector* v){ Vector u = C.c-p; double dist = Len(u); if(dcmp(dist - C.r)<0)return 0; if(dcmp(dist-C.r) == 0){ v[0] = Rotate(u,pi/2); return 1; } double ang = asin(C.r/dist); v[0] = Rotate(u,-ang); v[1] = Rotate(u,+ang); return 2; } //圆和圆之间公切线 int getTangents(Circle A,Circle B,Point *a,Point *b){ int cnt = 0; if(A.r<B.r){ swap(A,B); swap(a,b); } double d = Len(A.c-B.c); double rdiff = A.r-B.r; double rsum = A.r+B.r; if(dcmp(d - rdiff)<0)return 0;//内含 double base = atan2(B.c.y-A.c.y,B.c.x-A.c.x); if(!dcmp(d) && !dcmp(A.r-B.r))return -1;//无限的切线 if(!dcmp(d-rdiff)){//内切 a[cnt] = A.point(base); b[cnt] = B.point(base); cnt++; return 1; } double ang = acos((A.r-B.r)/d); a[cnt] = A.point(base+ang); b[cnt] = B.point(base+ang); cnt++; a[cnt] = A.point(base-ang); b[cnt] = B.point(base-ang); cnt++; if(!dcmp(d-rsum)){ a[cnt] = A.point(base); b[cnt] = B.point(pi+base); cnt++; }else if(dcmp(d - rsum)>0){ double ang = acos((A.r+B.r)/d); a[cnt] = A.point(base+ang); b[cnt] = B.point(pi+base+ang); cnt++; a[cnt] = A.point(base-ang); b[cnt] = B.point(pi+base-ang); cnt++; } return cnt; } //计算圆心角lat表示纬度,-90<=w<=90,lng表示经度 //返回两点所在大圆劣弧对应圆心角,0<=angle<=pi double angle(double lng1,double lat1,double lng2,double lat2){ double dlng=fabs(lng1-lng2)*pi/180; while (dlng>=pi+pi) dlng-=pi+pi; if (dlng>pi) dlng=pi+pi-dlng; lat1*=pi/180,lat2*=pi/180; return acos(cos(lat1)*cos(lat2)*cos(dlng)+sin(lat1)*sin(lat2)); } //计算距离,r为球半径 double line_dist(double r,double lng1,double lat1,double lng2,double lat2){ double dlng=fabs(lng1-lng2)*pi/180; while (dlng>=pi+pi) dlng-=pi+pi; if (dlng>pi) dlng=pi+pi-dlng; lat1*=pi/180,lat2*=pi/180; return r*sqrt(2-2*(cos(lat1)*cos(lat2)*cos(dlng)+sin(lat1)*sin(lat2))); } //计算球面距离,r为球半径 inline double sphere_dist(double r,double lng1,double lat1,double lng2,double lat2){ return r*angle(lng1,lat1,lng2,lat2); } int isPointInPolygon(Point p,vector poly){ int wn = 0; int n = poly.size(); for(int i=0;i ){ if(OnSegment(p,poly[i],poly[(i+1)%n])){ return -1;//in the edge } int k = dcmp(Cross(poly[(i+1)%n]-poly[i],p-poly[i])); int d1 = dcmp(poly[i].y-p.y); int d2 = dcmp(poly[(i+1)%n].y-p.y); if(k>0 && d1<=0 && d2>0)wn++; if(k<0 && d2<=0 && d1>0)wn--; } if(wn)return 1;//inside return 0;//outside } int ConvexHull(Point* p,int n,Point* ch){ sort(p,p+n); int m = 0; for(int i=0;i ){ while(m>1 && dcmp(Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])) <= 0)m--; ch[m++] = p[i]; } int k = m; for(int i=n-2;i>=0;i--){ while(m>k && dcmp(Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])) <= 0)m--; ch[m++] = p[i]; } if(n>1)m--; return m; } double PolygonArea(Point* A,int n){ double ans = 0; for(int i=0;i ) ans += Cross(A[i],A[(i+1)%n]); return ans/2; }
tangents
求圆的公切线
注意各种dcmp代替直接判断double的大小吧
struct Node{ Point a,b; double dist; bool operator < (const Node T)const{ return a<T.a; } }T[20]; Point a[20],b[20]; int main(){ while(true){ Circle A,B; A.read(),B.read(); if(!dcmp(A.c.x)&&!dcmp(A.c.y)&&!dcmp(A.r)&&!dcmp(B.c.x)&&!dcmp(B.c.y)&&!dcmp(B.r))break; int ans = getTangents(A,B,a,b); if(~ans){ printf("%d\n",ans); if(!ans)continue; for(int i=0;i){ T[i].a = a[i]; T[i].b = b[i]; T[i].dist = Len(a[i]-b[i]); } sort(T,T+ans); for(int i=0;i ){ printf("%.5f %.5f %.5f %.5f %.5f\n",T[i].a.x,T[i].a.y,T[i].b.x,T[i].b.y,T[i].dist); } }else{ printf("-1\n"); } } return 0; }
Board Wrapping
凸包板子
int main(){ int T; Point P[2500],ch[2500]; scanf("%d",&T); while(T--){ int n,pc = 0; double are1 = 0; scanf("%d",&n); for(int i=0;i){ double x,y,w,h,j,ang; scanf("%lf%lf%lf%lf%lf",&x,&y,&w,&h,&j); Point o(x,y); ang = -(j*pi/180); P[pc++] = o+Rotate(Vector(-w/2,-h/2),ang); P[pc++] = o+Rotate(Vector(w/2,-h/2),ang); P[pc++] = o+Rotate(Vector(-w/2,h/2),ang); P[pc++] = o+Rotate(Vector(w/2,h/2),ang); are1 += w*h; } int m = ConvexHull(P,pc,ch); //printf("%d\n",m); double are2 = PolygonArea(ch,m); printf("%.1f %%\n",are1*100/are2); } return 0; }
/*author:revolIA*//*492357816*/#include
Point L = Point(max(Lx.x,Ly.x),max(Lx.y,Ly.y)); Point R = Point(min(Rx.x,Ry.x),min(Rx.y,Ry.y));
return (L.x<=R.x) && (L.y<=R.y);}bool OnSegment(Point P,Point x,Point y){//点在线段上 if(P == x||P == y)return 1; return !dcmp(Cross(x-P,y-P))&&dcmp(Dot(P-x,P-y))<0;}bool straddle(Point x1,Point y1,Point x2,Point y2){//跨立实验(线段是否有交点) if(!quickRepel(x1,y1,x2,y2))return 0; double c1 = Cross(y1-x1,x2-x1),c2 = Cross(y1-x1,y2-x1); double c3 = Cross(y2-x2,x1-x2),c4 = Cross(y2-x2,y1-x2); return dcmp(c1)*dcmp(c2)<=0 && dcmp(c3)*dcmp(c4)<=0; //允许部分重合或在端点重合 //return dcmp(c1)*dcmp(c2)<0 && dcmp(c3)*dcmp(c4)<0; //必须只有一个交点且不在端点上}Point LinearIntersection(Point P,Vector v,Point Q,Vector w){//解直线交点 assert(v != w);//Parallel 平行线 Vector u = P-Q; double t = Cross(w,u)/Cross(v,w); return P+v*t;}Point GetLineProjection(Point P,Point A,Point B){//P投影到AB上的点 Vector v = B-A; return A+v*(Dot(v,P-A)/Dot(v,v));}Point SymmetricPoint(Point P,Point A,Point B){//P关于AB的对称点 return GetLineProjection(P,A,B)*2.0-P;}double DistanceToline(Point P,Point A,Point B){//点到直线距离 Vector v1 = B-A,v2 = P-A; return fabs(Cross(v1,v2))/Len(v1);}double DistanceToSegment(Point P,Point A,Point B){//点到线段距离 if(A == B)return Len(P-A); Vector v1 = B-A,v2 = P-A,v3 = P-B; if(dcmp(Dot(v1,v2))<0)return Len(v2); if(dcmp(Dot(v1,v3))>0)return Len(v3); return fabs(Cross(v1,v2))/Len(v1);}//直线struct Line{ Point p; Vector v; double ang; Line(){} Line(Point p,Vector v):p(p),v(v){ang = atan2(v.y,v.x);} Point point(double t){ return p+v*t; } bool operator < (const Line& T)const{ return ang