凸包

转载摘自大神博客:

https://thewalker88.com/?p=84

求组成凸包的点坐标,周长面积等问题

针对这个问题:Melkman复杂度n,且可以在线处理,而Graham复杂度nlogn(因为必须先排序)
平面上有一个简单多边形,沿着多边形的边,按照逆时针的顺序给出多边形的顶点的坐标,要求你求出此多边形的凸包。
如果是一般散点集问题的话,那它跟Graham复杂度相同,均需要先排个序nlogn

melkman算法想象成渔网网鱼就成,左右边同时包揽

struct Vector
{
double x, y;
};
struct Point
{
double x, y;
} p[N],dq[N];
bool cmp(Point a, Point b)
{
if (a.y == b.y)
return a.x < b.x;
return a.y < b.y;
}
double Cross(Vector A, Vector B) { return A.x * B.y - A.y * B.x; }//叉乘,右手螺旋,左上正右下负
double side(Point a, Point b, Point p)//判断p在a->b直线那一侧
{
Vector A = (Vector){b.x - a.x, b.y - a.y};
Vector B = (Vector){p.x - a.x, p.y - a.y};
return Cross(A, B);
}

void Melkman(int n, int &head, int &tail)
{
sort(p + 1, p + 1 + n, cmp);//如果是处理一般点集问题,这里排序保证了这只“渔网”从西南角往东北角突击
dq[head = n] = p[2];//这里直接丢1,2进来,3并不需要如网上说的手动调
dq[tail = n + 1] = p[1];
dq[++tail] = p[2];
For(i, 3, n)
{
// if (side(dq[head + 1], dq[head], p[i])<0 && side(dq[tail - 1], dq[tail], p[i])>0)//如果是处理简单多边形的题要加这句话
// continue;
while (tail - head >= 2 && side(dq[head + 1], dq[head], p[i]) >= 0)//head+1->head从左路包揽敌人,如果有更左侧的鱼,那就调整角度向左扩张渔网
++head;
dq[--head] = p[i];
while (tail - head >= 2 && side(dq[tail - 1], dq[tail], p[i]) <= 0 )//tail-1->tail从右路包揽敌人
--tail;
dq[++tail] = p[i];
}
}
For(i,head,tail-1)//因为head和tail存的值一定相同,输出点坐标输出一边就行
cout<<dq[i].x<<" "<<dq[i].y<<endl;
原文地址:https://www.cnblogs.com/planche/p/9426915.html