凸包模板
凸包模板
写在前面:预备函数
参考博客:https://www.cnblogs.com/nyist-TC-LYQ/p/7208054.html
一、 点的定义:
1 int n,tot;//n为二维平面上点的个数,tot为凸包上点的个数
2 struct node
3 {
4 int x,y;
5 }a[N],p[N];//p[]用来储存凸包
二、距离公式:
1 double dis(node a,node b)
2 {
3 return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
4 }
三、叉积:返回结果为正说明p2在向量p0p1的左边(三点构成逆时针方向);返回结果为负说明p2在向量p0p1的右边(三点构成顺时针方向);返回结果为0则三点共线(叉积的性质很重要)
1 double multi(node p0,node p1,node p2)
2 {
3 return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
4 }
四、极角排序:根据坐标系内每一个点与x轴所成的角,逆时针比较,按照角度从小到大排序。
1 int cmp(node p1,node p2)//极角排序;
2 {
3 int x=multi(p1,p2,a[0]);
4 if(x>0||(x==0&&dis(p1,a[0])<dis(p2,a[0]))) return 1;
5 return 0;
6 }
重点和核心:graham 算法:O(nlogn)
1 void Graham() 2 { 3 int k=0; 4 for(int i=0;i<n;i++) 5 if(a[i].y<a[k].y||(a[i].y==a[k].y&&a[i].x<a[k].x)) k=i; 6 swap(a[0],a[k]); 7 sort(a+1,a+n,cmp); 8 tot=2,p[0]=a[0],p[1]=a[1]; 9 for(int i=2;i<n;i++) 10 { 11 while(tot>1&&multi(p[tot-1],p[tot-2],a[i])>=0) tot--; 12 p[tot++]=a[i]; 13 } 14 }
以上连接起来就是求凸包的模板。
雪儿言