凸包

Graham算法

先找出以\(y\)值为第一关键字和以\(x\)值为第二关键字最小的点,以其作为基准点

然后对剩下的点进行极角序排序

向栈中加点,并维护凸性,最终栈中的点即为凸包上的点

复杂度即为排序的复杂度\(O(n\ log\ n)\)

\(code:\)

struct point
{
	double x,y;
}p[maxn],st[maxn];
point operator -(const point &a,const point &b)
{
    return (point){a.x-b.x,a.y-b.y};
}
double operator *(const point &a,const point &b)
{
    return a.x*b.y-a.y*b.x;
}
double dis(const point &a,const point &b)
{
	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
bool cmp1(const point &a,const point &b)
{
    if(a.x==b.x) return a.y<b.y;
    return a.x<b.x;
}
bool cmp2(const point &a,const point &b)
{
	if((a-p[1])*(b-p[1])==0) return dis(a,p[1])<dis(b,p[1]);
	return (b-a)*(p[1]-a)>0;
}
void graham()
{
	sort(p+1,p+n+1,cmp1);
	sort(p+2,p+n+1,cmp2);
	st[1]=p[1],top=1;
	for(int i=2;i<=n;++i)
	{
		while(top>1&&(st[top-1]-p[i])*(st[top]-p[i])<=0) top--;
		st[++top]=p[i];
	}
}

旋转卡壳

对踵点,如果过凸多边形上两点作一对平行线,使得整个多边形都在这两条线之间,那么这两个点被称为一对对踵点,直径一定会在对踵点中产生

逆时针枚举边,然后从上次枚举到对踵点的继续逆时针向后枚举来求解

实现时用双指针法来保证\(O(n)\)的复杂度,用叉积求面积来判断点到边的距离

\(code:\)

struct point
{
	int x,y;
}p[maxn],st[maxn];
point operator -(const point &a,const point &b)
{
    return (point){a.x-b.x,a.y-b.y};
}
double operator *(const point &a,const point &b)
{
    return a.x*b.y-a.y*b.x;
}
int dis(const point &a,const point &b)
{
	return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
bool cmp1(const point &a,const point &b)
{
    if(a.x==b.x) return a.y<b.y;
    return a.x<b.x;
}
bool cmp2(const point &a,const point &b)
{
	if((a-p[1])*(b-p[1])==0) return dis(a,p[1])<dis(b,p[1]);
	return (b-a)*(p[1]-a)>0;
}
void graham()
{
	sort(p+1,p+n+1,cmp1);
	sort(p+2,p+n+1,cmp2);
	st[1]=p[1],top=1;
	for(int i=2;i<=n;++i)
	{
		while(top>1&&(st[top-1]-p[i])*(st[top]-p[i])<=0) top--;
		st[++top]=p[i];
	}
}
void get()
{
	int j=1;
	st[top+1]=st[1];
	for(int i=1;i<=top;++i)
	{
		while((st[i+1]-st[i])*(st[j]-st[i])<(st[i+1]-st[i])*(st[j+1]-st[i])) j=(j+1)%top;
		ans=max(ans,max(dis(st[i],st[j]),dis(st[i+1],st[j])));
	}
}
posted @ 2020-01-22 20:41  lhm_liu  阅读(158)  评论(0编辑  收藏  举报