凸包 极角排序

mac2024-11-24  43

const int maxn=1005; const double eps=1e-10; struct point{ int x; int y; point(){} point(int xx,int yy):x(xx),y(yy){} bool friend operator <(const point &a,const point &b){ if(a.x==b.x) return a.y<b.y; return a.x<b.x; } bool friend operator ==(const point &a,const point &b){ return a.x==b.x&&a.y==b.y; } bool friend operator !=(const point &a,const point &b){ return !(a==b); } point friend operator -(const point &a,const point &b){ return point(a.x-b.x,a.y-b.y); } }p[maxn],O,q[2*maxn+10];//p:原本的点集 O:中心点 q:凸包里的点集 bool cmp(point a,point b)//顺时针极角排序 { return a.x*b.y>a.y*b.x; } double cross2(point a,point b,point c) { return (c.x-a.x)*(b.y-a.y)-(c.y-a.y)*(b.x-a.x); } bool cmp1(point p2,point p3)//以O为中心,极角排序 { return cross2(O,p2,p3)<eps; } double cross(point a,point b){//叉乘 return a.x*b.y-b.x*a.y; } double dis(point a,point b){//两点间的距离 return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } int PointOffLine( point pt, point start, point end) { //判断点point与线段(start,end)的关系 //返回值:>0 点在矢量start,end的逆时针方向 // =0 点在线段(start,end)或其延长线上 // <0 点在矢量start,end的顺时针方向 return ((pt.x - end.x)*(start.y - end.y)-(start.x - end.x)*(pt.y - end.y)); } int n,m; double Andrew(){//无序求凸包 sort(p,p+n); m=0; for(int i=0;i<n;i++){ while(m>1&&cross(q[m-1]-q[m-2],p[i]-q[m-2])<=0) m--; //等号决定共线的点是否进入栈,也就是是否要凸边上的点 q[m++]=p[i]; } int o=m; for(int i=n-2;i>=0;i--){ while(m>o&&cross(q[m-1]-q[m-2],p[i]-q[m-2])<=0) m--; //等号决定共线的点是否进入栈,也就是是否要凸边上的点 q[m++]=p[i]; } if(n>1) m--; double ans=0; for(int i=1;i<m;i++){ ans+=dis(q[i],q[i-1]); } return ans+dis(q[0],q[m-1]); } double Melkman(){//有序快速求凸包 int head,tail; head=tail=n; q[tail++]=p[0]; int i; for(i=0;i<n-1;i++){ q[tail]=p[i]; if(cross(p[i]-q[head],p[i+1]-q[head])) break; } if(n==1) return 0; if(n==2) return dis(p[0],p[1]); if(n==3){ return dis(p[0],p[1])+dis(p[0],p[2])+dis(p[1],p[2]); } q[--head]=q[++tail]=p[++i]; if(cross(q[n+1]-q[n],q[n+2]-q[n])<0) swap(q[n],q[n+1]); for(++i;i<n;i++){ if(cross(q[tail]-q[tail-1],p[i]-q[tail-1])>0 &&cross(q[head]-q[head+1],p[i]-q[head+1])<0) continue; //凹凸全部满足,这个点是内部点,不考虑 while(tail-head>1&&cross(q[tail]-q[tail-1],p[i]-q[tail-1])<=0) tail--; q[++tail]=p[i]; while(tail-head>1&&cross(q[head]-q[head+1],p[i]-q[head+1])>=0) head++; q[--head]=p[i]; } double ans=0; for(int i=head;i<tail;i++){ ans+=dis(q[i],q[i+1]); } return ans; } double Area()//凸包求面积 { if(m<3)return 0; int i; double ret=0.0; for(i=2; i<m; i++) { ret+=fabs(cross2(q[0],q[i-1],q[i])/2.0); } return ret; } double RC(int len){ //len 指凸包点集合长度 vic[] 凸包点 cross 叉积 同上 int t=1; double ans=dis(p[0],p[1]); for(int i=0;i<len;i++){ while(abs(cross(p[(i+1)%len]-p[i],p[t]-p[i])) <abs(cross(p[(i+1)%len]-p[i],p[(t+1)%len]-p[i]))) t=(t+1)%len; ans=max(ans,max(dis(p[t],p[i]),dis(p[(i+1)%len],p[t]))); } return ans; }
最新回复(0)