平面凸包(jarvis算法)

算法大体思想:形成凸包的构造函数是这样的,找到一条直线l过其中一点(记为A)并且所有其他点都在l的同侧(显然这样的直线一定可以找到),则A必为凸包上的一点。让l以A为轴点向一个方向(比如:顺时针方向)不断旋转,直到l碰到除A以外的第一个点(记为B)。如果同时碰到多于一个点,则取与A点距离最大的。再次以B为轴点,向相同的方向的旋转l,重复上述过程,直到l回到A点。

附上代码:


#include<bits/stdc++.h>

using namespace std;

const double eps=1e-10;

int n;

struct point{
    double x,y;
    point(){}
    point(double _x,double _y){
        x=_x;y=_y;
    }
    point operator - (point &p){
        return point(x-p.x,y-p.y);
    }
}a[100051];

int p[100051];

double cross(point a,point b)
{
    return a.x*b.y-a.y*b.y;
}

double dist2(point p1,point p2)
{
    return (p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y);
}

bool judgeonleft(point p0,point p1,point p2)
{
    double s=cross(p1-p0,p2-p0);
    return s<0||(s==0&&(dist2(p1,p0)>=dist2(p2,p0)));
}

int main()
{
    scanf("%d",&n);
    int first=1;
    for(int i=1;i<=n;i++){
        scanf("%lf%lf",&a[i].x,&a[i].y);
        if(a[i].x<a[first].x||(a[i].x==a[first].x&&a[i].y<a[first].y)){
            first=i;
        }
    }
    int top=0;
    p[++top]=first;
    do{
        int ep=1;
        for(int i=2;i<=n;i++){
            if(judgeonleft(a[p[top]],a[i],a[ep])){
                ep=i;
            }
        }
        p[++top]=ep;
    }while(p[top]!=first);
    top--;
    printf("%d\n",top);
    for(int i=1;i<=top;i++){
        printf("%.2f %.2f\n",a[p[i]].x,a[p[i]].y);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zhouzi2018/article/details/82177489