您的位置:首页 > 其它

凸包

2016-09-28 19:29 169 查看
凸包是计算几何中的基本问题,在介绍凸包算法之前,先来解决几个计算几何中的几个基础算法。

计算几何基本算法

叉乘

double Cross(Point& p,Point& q,Point&  r)
{
return (q.x-p.x)*(r.y-p.y) - (r.x-p.x)*(q.y-p.y);
}


在解析几何中我们知道叉乘的绝对值表示所围成的面积的两倍,而叉乘的值可以用来判断点在向量的左侧还是右侧

点乘

double Dot(int p,int q,int r)
{
return (P[r].x-P[p].x)*(P[r].x-P[q].x)+(P[r].y-P[p].y)*(P[r].y-P[q].y);//在两点中间,等于0是为了应对从点的情况
}


点乘的符号在凸包中可以用来判断共线点在向量的中间还是两侧。

LTL(lowest-than-left)最下边最左端点

这个是比较简单的

int LTL(int n)
{
int ltl = 0;
for(int i=1 ; i<n ; ++i)
if(P[ltl].y==P[i].y)
{
if(P[ltl].x>P[i].x)
ltl = i;
}else if(P[ltl].y>P[i].y)
{
ltl = i;
}
return ltl;
}


凸包中的几个简单算法

Jevies-March

void  Jevis_March(int n)
{
ltl = LTL(n);
int k = ltl;
do{
int s = (0==k?1:0);
for(int i =0 ; i<n ; ++i)
{
if(i!=k&&i!=s )//不在左边并且不在中间更新s
{
double area2 = Cross(P[k],P[s],P[i]);
if(area2<0 || (area2 == 0 && !between(k,s,i)))s = i;//寻找最右点,如果共线则寻找线端点
}
}
P[k].next = s;
k = s;
}while(k!=ltl);
}


算法复杂度O(nh)这是一个与凸包极点的个数相关的算法,先找到一个极点(一般就是LTL)然后从这个极点出发每次找出最右边的一个点,当扫完的时候凸包也就构造出来了。

Graham_Scan

这是Graham创造的一个O(nlgn)的一个算法。简单的说就是先找到一个极点,然后再把剩下的点把所有的点按照极角的大小排序,这样排出来的

void Graham_Scan(long long n)
{
ltl = LTL(n);
swap(P[ltl],P[0]);
ltl = 0;
sort(P+1,P+n,cmp);

vector<int>s;
s.push_back(ltl);
//应对重合起始点
int  next = 1;
s.push_back(next);
for(int i=next+1; i<n ;)
{
if(s.size()<2)
{
s.push_back(i);i++;
}else{
double area2 = Cross(P[s[s.size()-2]],P[s[s.size()-1]],P[i]);
if(area2>0)
{
s.push_back(i);i++;
}else
{
s.pop_back();
}
}
}
//串接凸包上的点
for(int i=0 ; i<s.size()-1 ; ++i)
P[s[i]].next = s[i+1];
P[s[s.size()-1]].next =s[0];
}


这是一个经典的算法,基于这个算法,Andrew提出了一个更快数值稳定性更好的算法(PS:我并不知道快在哪儿,稳定在哪儿。。)

Andrew

int Andrew(int n)
{
int m = 0;
sort(P,P+n);
for(int i=0 ; i<n ; ++i)
{
while(m>1 && Cross(P[ch[m-2]],P[ch[m-1]],P[i])<=0)m--;
ch[m++] = i;
}
int k = m;

for(int i=n-2 ; i>=0 ;--i )
{
while(m>k && Cross(P[ch[m-2]],P[ch[m-1]],P[i])<=0)m--;
ch[m++] = i;
}
if(n>1)m--;
return m;
}


这个算法其实思想是和Graham_Scan的朴素思想是想通的,唯一的优点,个人认为是实现起来比较简单,比如排序不需要再用极角来排序了,直接用坐标来排序是比较容易,也是比较简单的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  凸包 计算几何