数据结构:
struct Point {
double x;
double y;
Point(double a = 0, double b = 0) : x(a), y(b) {}
friend bool operator < (const Point &l, const Point &r) {//以y为第一优先级,x为第二优先级
return l.y < r.y || (l.y == r.y && l.x < r.x);
}
} p[MAXN];判断凸包:
double mult(const Point &a, const Point &b, const Point &o) {
return (a.x - o.x) * (b.y - o.y) >= (b.x - o.x) * (a.y - o.y);//b到o的斜率大于a到o的斜率
}
int Graham(Point *p,int n,Point* Set)//p为点集(从1开始一共有n个)set为逆时针以最左下开始的构成凸包的点集,返回值是构成凸包的点的个数
{
sort(p+1,p+n+1);
int head;
if (n<3) return 0;
Set[1]=p[1];Set[2]=p[2];
head=2;
for (int k=3;k<=n;k++)
{
while(head!=1)
if (mult(p[k],Set[head],Set[head-1])) head--;
else break;
Set[++head]=p[k];
}
int len=head;
Set[++head]=p[n-1];
for (int k=n-2;k>=1;k--)
{
while(head!=len)
if (mult(p[k],Set[head],Set[head-1])) head--;
else break;
Set[++head]=p[k];
}
return --head;
}
为什么要判两遍呢,其实我们可以看看排序算法
我们的p[0]其实是左下的一个点,然后p[n-1]其实是右上的一个点
我们正着来一遍的话就只是逆时针从左下到右上点做了一个凸包,接下来还要从右上到左上做一个凸包,这才能算是完整的凸包
同时我们可以看到,我们起点入队了两次,所以咱们最后要return --head;
本文详细介绍了使用Graham扫描算法构建二维平面上点集的凸包过程。通过定义特定的数据结构和比较运算符,实现了一种高效算法。该算法首先找到最左下方的点作为起点,并以此为基础进行两轮扫描,确保生成的凸包完整覆盖所有点。
723

被折叠的 条评论
为什么被折叠?



