计算几何初步(刷蓝书)
Posted revolia-room
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了计算几何初步(刷蓝书)相关的知识,希望对你有一定的参考价值。
头文件
#include<bits/stdc++.h> #define max(a,b) (a>b?a:b) #define min(a,b) (a<b?a:b) using namespace std; typedef long long ll; const int maxn = 1e3+7; const double esp = 1e-6; int dcmp(double x) if(fabs(x)<esp)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 A.x<B.x || (A.x == B.x&&A.y<B.y); typedef Point Vector; struct Circle Point x; double r; void read() x.read(); scanf("%lf",&r); ; 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);
例题:
Morley‘s Theorem
https://vjudge.net/problem/UVA-11178
注意理解三等分角和三等分边不是一个概念
Point GetPoint(Point A,Point B,Point C) Vector v1 = C-B; double a1 = Angle(A-B,v1); v1 = Rotate(v1,a1/3); Vector v2 = B-C; double a2 = Angle(A-C,v2); v2 = Rotate(v2,-a2/3); return LinearIntersection(B,v1,C,v2); int main() int T; scanf("%d",&T); while(T--) Point A,B,C; A.read(),B.read(),C.read(); Point D = GetPoint(A,B,C); Point E = GetPoint(B,C,A); Point F = GetPoint(C,A,B); printf("%.6f %.6f ",D.x,D.y); printf("%.6f %.6f ",E.x,E.y); printf("%.6f %.6f\n",F.x,F.y); return 0;
好看的一笔画LA3263
= = 我没找着这个题
狗的距离
https://vjudge.net/problem/UVA-11796
因为没有加速度,所以可以一条狗为参考系,考虑另一条狗的贡献
每次至少跳一个点,所以复杂度也可以保证最多n+m
模拟即可
Point A[maxn],B[maxn]; double Max,Min; void update(Point P,Point A,Point B) Min = min(Min,DistanceToSegment(P,A,B)); Max = max(Max,Len(P-A)); Max = max(Max,Len(P-B)); int main() int T,n,m,Case = 0; scanf("%d",&T); while(T--) scanf("%d%d",&n,&m); for(int i=0;i<n;i++)A[i].read(); for(int i=0;i<m;i++)B[i].read(); double LenA = 0,LenB = 0; for(int i=0;i<n-1;i++) LenA += Len(A[i+1]-A[i]); for(int i=0;i<m-1;i++) LenB += Len(B[i+1]-B[i]); int Sa = 0,Sb = 0; Point Pa = A[0],Pb = B[0]; Min = 1e9,Max = -1e9; while(Sa<n-1 && Sb<m-1) double La = Len(A[Sa+1]-Pa); double Lb = Len(B[Sb+1]-Pb); double T = min(La/LenA,Lb/LenB); Vector Va = (A[Sa+1]-Pa)/La*T*LenA; Vector Vb = (B[Sb+1]-Pb)/Lb*T*LenB; update(Pa,Pb,Pb+Vb-Va); Pa = Pa+Va; Pb = Pb+Vb; if(Pa == A[Sa+1])Sa++; if(Pb == B[Sb+1])Sb++; printf("Case %d: %.0f\n",++Case,Max-Min); return 0;
以上是关于计算几何初步(刷蓝书)的主要内容,如果未能解决你的问题,请参考以下文章