太难的比如三维凸包已过滤,估计NOI考不了毒瘤计算几何吧,不过还是背些简单的吧。
二维凸包:https://www.luogu.org/problemnew/show/P2742
#include<bits/stdc++.h> using namespace std; struct node{double x,y;}p[10001],q[10001]; int n,top; double ans; node operator-(node a,node b){return(node){a.x-b.x,a.y-b.y};} double dis(node a,node b){return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));} double cross(node p1,node p2){return p1.x*p2.y-p2.x*p1.y;} bool cmp(node a,node b) { if(!cross(a-p[0],b-p[0]))return dis(a,p[0])<dis(b,p[0]); return cross(a-p[0],b-p[0])>0; } void Graham() { int k=0; for(int i=1;i<n;i++)if(p[i].y<p[k].y||p[i].y==p[k].y&&p[i].x<p[k].x)k=i; swap(p[0],p[k]); sort(p+1,p+n,cmp); q[0]=p[0],q[1]=p[1],q[2]=p[2]; top=2; for(int i=3;i<n;i++) { while(top&&cross(p[i]-q[top-1],q[top]-q[top-1])>=0)top--; q[++top]=p[i]; } q[++top]=p[0]; for(int i=0;i<top;i++)ans+=dis(q[i],q[i+1]); } int main() { scanf("%d",&n); for(int i=0;i<n;i++)scanf("%lf%lf",&p[i].x,&p[i].y); Graham(); printf("%0.2f",ans); }
旋转卡壳:https://www.lydsy.com/JudgeOnline/problem.php?id=1185
#include<cstdio> #include<algorithm> #include<cmath> using namespace std; const int N=5e4+7; const double eps=1e-8; struct point{double x,y;}p[N],q[N],t[5]; bool operator<(point a,point b){return fabs(a.y-b.y)<eps?a.x<b.x:a.y<b.y;} point operator+(point a,point b){return(point){a.x+b.x,a.y+b.y};} point operator-(point a,point b){return(point){a.x-b.x,a.y-b.y};} point operator*(point a,double b){return (point){a.x*b,a.y*b};} double cross(point a,point b){return a.x*b.y-a.y*b.x;} double dot(point a,point b){return a.x*b.x+a.y*b.y;} double dis(point a){return sqrt(a.x*a.x+a.y*a.y);} int n,top; double ans=1e18; bool cmp(point a,point b) { double t=cross(a-p[1],b-p[1]); if(fabs(t)<eps)return dis(p[1]-a)-dis(p[1]-b)<0; return t>0; } void Graham() { for(int i=2;i<=n;i++)if(p[i]<p[1])swap(p[i],p[1]); sort(p+2,p+n+1,cmp); q[top=1]=p[1]; for(int i=2;i<=n;i++) { while(top>1&&cross(q[top]-q[top-1],p[i]-q[top])<eps)top--; q[++top]=p[i]; } q[0]=q[top]; } void RC() { int l=1,r=1,p=1; double L,R,D,H; for(int i=0;i<top;i++) { D=dis(q[i]-q[i+1]); while(cross(q[i+1]-q[i],q[p+1]-q[i])-cross(q[i+1]-q[i],q[p]-q[i])>-eps)p=(p+1)%top; while(dot(q[i+1]-q[i],q[r+1]-q[i])-dot(q[i+1]-q[i],q[r]-q[i])>-eps)r=(r+1)%top; if(!i)l=r; while(dot(q[i+1]-q[i],q[l+1]-q[i])-dot(q[i+1]-q[i],q[l]-q[i])<eps)l=(l+1)%top; L=dot(q[i+1]-q[i],q[l]-q[i])/D,R=dot(q[i+1]-q[i],q[r]-q[i])/D; H=fabs(cross(q[i+1]-q[i],q[p]-q[i])/D); double tmp=(R-L)*H; if(tmp<ans) { ans=tmp; t[0]=q[i]+(q[i+1]-q[i])*(R/D); t[1]=t[0]+(q[r]-t[0])*(H/dis(t[0]-q[r])); t[2]=t[1]-(t[0]-q[i])*((R-L)/dis(q[i]-t[0])); t[3]=t[2]-(t[1]-t[0]); } } } int main() { scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%lf%lf",&p[i].x,&p[i].y); Graham(); RC(); printf("%.5lf\n",ans); int p=0; for(int i=1;i<=3;i++)if(t[i]<t[p])p=i; for(int i=0;i<=3;i++)printf("%.5lf %.5lf\n",t[(i+p)%4].x,t[(i+p)%4].y); }
半平面交:https://www.lydsy.com/JudgeOnline/problem.php?id=1038
#include<cstdio> #include<algorithm> #include<cmath> using namespace std; const int N=1010; struct point{double x,y;}p[N],a[N]; struct line{point a,b;double slop;}l[N],q[N]; int n,cnt,tot,top; double ans=1e18; point operator-(point a,point b){return (point){a.x-b.x,a.y-b.y};} double operator*(point a,point b){return a.x*b.y-a.y*b.x;} bool operator<(line a,line b){return a.slop==b.slop?(a.b-a.a)*(b.b-a.a)>0:a.slop<b.slop;} point inter(line a,line b) { double k1=(b.b-a.a)*(a.b-a.a),k2=(a.b-a.a)*(b.a-a.a),t=k2/(k1+k2); return (point){b.a.x+t*(b.b.x-b.a.x),b.a.y+t*(b.b.y-b.a.y)}; } bool judge(line a,line b,line c){return(c.b-c.a)*(inter(a,b)-c.a)<0;} void hpi() { int qs=0,qe=1; for(int i=1;i<=cnt;i++) { if(l[i].slop!=l[i-1].slop)tot++; l[tot]=l[i]; } cnt=tot; q[0]=l[1],q[1]=l[2]; for(int i=3;i<=cnt;i++) { while(qs<qe&&judge(q[qe-1],q[qe],l[i]))qe--; while(qs<qe&&judge(q[qs+1],q[qs],l[i]))qs++; q[++qe]=l[i]; } while(qs<qe&&judge(q[qe-1],q[qe],q[qs]))qe--; while(qs<qe&&judge(q[qs+1],q[qs],q[qe]))qs++; tot=0; for(int i=qs;i<qe;i++)a[++tot]=inter(q[i],q[i+1]); } int main() { scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%lf",&p[i].x); for(int i=1;i<=n;i++)scanf("%lf",&p[i].y); p[0].x=p[1].x,p[0].y=100001; p[n+1].x=p[n].x,p[n+1].y=100001; for(int i=1;i<=n;i++)l[++cnt].a=p[i-1],l[cnt].b=p[i],l[++cnt].a=p[i],l[cnt].b=p[i+1]; for(int i=1;i<=cnt;i++)l[i].slop=atan2(l[i].b.y-l[i].a.y,l[i].b.x-l[i].a.x); sort(l+1,l+cnt+1); hpi(); for(int k=1;k<=tot;k++) for(int i=1;i<n;i++) { point t=(point){a[k].x,-1}; if(a[k].x>=p[i].x&&a[k].x<=p[i+1].x) ans=min(ans,a[k].y-inter((line){p[i],p[i+1]},(line){t,a[k]}).y); } for(int k=1;k<=n;k++) for(int i=1;i<tot;i++) { point t=(point){p[k].x,-1}; if(p[k].x>=a[i].x&&p[k].x<=a[i+1].x) ans=min(ans,inter((line){a[i],a[i+1]},(line){t,p[k]}).y-p[k].y); } printf("%.3lf",ans); }
凸包的闵可夫斯基和:https://www.luogu.org/problemnew/show/P4557
#include<bits/stdc++.h> #define ll long long using namespace std; const int N=1e5+9; struct point{ ll x,y; point(ll _x=0,ll _y=0):x(_x),y(_y){} friend point operator+(const point&a,const point&b){return point(a.x+b.x,a.y+b.y);} friend point operator-(const point&a,const point&b){return point(a.x-b.x,a.y-b.y);} friend ll operator*(const point &a,const point &b){return a.x*b.y-a.y*b.x;} ll dis(){return x*x+y*y;} }p[N],p1[N],p2[N],t[N],v1[N],v2[N]; bool cmp(point a,point b) { ll ret=(a-t[1])*(b-t[1]); if(ret)return ret>0; else return(a-t[1]).dis()<(b-t[1]).dis(); } int n,m,Q,top; int Graham(point *p,int cnt) { for(int i=1;i<=cnt;i++)t[i]=p[i]; for(int i=2;i<=cnt;i++)if(t[i].x<t[1].x||t[i].x==t[1].x&&t[i].y<t[1].y)swap(t[1],t[i]); sort(t+2,t+cnt+1,cmp); int tp=1; for(int i=2;i<=cnt;i++) { while(tp>=2&&(t[tp]-t[tp-1])*(t[i]-t[tp-1])<=0)tp--; t[++tp]=t[i]; } for(int i=1;i<=tp;i++)p[i]=t[i]; return tp; } void work() { for(int i=1;i<=n;i++)v1[i]=p1[i%n+1]-p1[i]; for(int i=1;i<=m;i++)v2[i]=p2[i%m+1]-p2[i]; int l1=1,l2=1; p[top=1]=p1[1]+p2[1]; while(l1<=n&&l2<=m)p[++top]=p[top-1]+(v1[l1]*v2[l2]>=0?v1[l1++]:v2[l2++]); while(l1<=n)p[++top]=p[top-1]+v1[l1++]; while(l2<=m)p[++top]=p[top-1]+v2[l2++]; top=Graham(p,top); } int inner(point x) { if((x-p[1])*(p[2]-p[1])>0||(x-p[1])*(p[top]-p[1])<0)return 0; int l=2,r=top,pos=l; while(l<=r) { int mid=(l+r)/2; if((p[mid]-p[1])*(x-p[1])>=0)pos=mid,l=mid+1; else r=mid-1; } return(p[pos%top+1]-p[pos])*(x-p[pos])>=0; } int main() { scanf("%d%d%d",&n,&m,&Q); for(int i=1;i<=n;i++)scanf("%lld%lld",&p1[i].x,&p1[i].y); for(int i=1;i<=m;i++)scanf("%lld%lld",&p2[i].x,&p2[i].y),p2[i].x*=-1,p2[i].y*=-1; n=Graham(p1,n);m=Graham(p2,m); work(); while(Q--) { point q; scanf("%lld%lld",&q.x,&q.y); printf("%d\n",inner(q)); } }
simpson积分:https://www.lydsy.com/JudgeOnline/problem.php?id=2178
#include<cstdio> #include<cmath> #include<algorithm> #define Fabs(x) ((x)>0?(x):-(x)) using namespace std; typedef pair<double,double>pii; const int N=1007; const double pi=acos(-1.0),eps=1e-13,inf=1e100; struct point{int x,y;}; double dis(point a,point b){return sqrt((double)(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));} struct node{ point p;int r; void read(){scanf("%d%d%d",&p.x,&p.y,&r);} pii f(double x) { if(r<=fabs(p.x-x))return pii(0,0); double t=sqrt(r*r-(p.x-x)*(p.x-x)); return pii(p.y-t,p.y+t); } }a[N]; bool operator<(node a,node b){return a.p.x<b.p.x;} int n,ban[N]; pii p[N]; double F(double x) { double ret=0,lst=-inf; int cnt=0; for(int i=1;i<=n;i++) { p[++cnt]=a[i].f(x); if(p[cnt]==pii(0,0))cnt--; } sort(p+1,p+cnt+1); for(int i=1;i<=cnt;i++) if(p[i].first>lst)ret+=p[i].second-p[i].first,lst=p[i].second; else if(p[i].second>lst)ret+=p[i].second-lst,lst=p[i].second; return ret; } double simpson(double l,double r,double mid,double cl,double cr,double s) { double fl=F((l+mid)/2),fr=F((mid+r)/2); double ret=(r-l)*(cl+cr+4*s)/6,vl=(mid-l)*(cl+s+4*fl)/6,vr=(r-mid)*(cr+s+4*fr)/6; if(Fabs(vl+vr-ret)<eps)return ret; return simpson(l,mid,(l+mid)/2,cl,s,fl)+simpson(mid,r,(mid+r)/2,s,cr,fr); } int main() { scanf("%d",&n); double l=inf,r=-inf; for(int i=1;i<=n;i++) a[i].read(),l=min(l,(double)a[i].p.x-a[i].r),r=max(r,(double)a[i].p.x+a[i].r); sort(a+1,a+n+1); for(int i=1;i<=n;i++) if(!ban[i])for(int j=i+1;j<=n;j++) if(!ban[j]&&dis(a[i].p,a[j].p)+a[j].r<=a[i].r)ban[j]=1; for(int i=1;i<=n;i++)if(ban[i])swap(ban[i],ban[n]),swap(a[i--],a[n--]); printf("%.3lf",simpson(l,r,(l+r)/2,0,0,F((l+r)/2))); }
扫描线当数据结构吧