凸包之Andrew算法——模板整理

来源:互联网 发布:中国实际领土知乎 编辑:程序博客网 时间:2024/05/22 14:49

是Graham的变种。水平扫描,分别构造上下凸壳,然后把两者接起来。
感觉比Graham好用。
复杂度O(nlog2n) (排序)

#include<cmath>#include<cstdio>#include<algorithm>using namespace std;const int maxn=1100;const double eps=1e-9;int dcmp(double x){    if(fabs(x)<eps) return 0;    return x<0?-1:1;}struct Point{    double x,y;    Point(double x=0,double y=0):x(x),y(y){}    bool operator < (const Point &b)const{        if(x<b.x) return true;        if(x>b.x) return false;        return y<b.y;    }};typedef Point Vector;Vector operator - (Point A,Point B){ return Vector(A.x-B.x,A.y-B.y); }double Cross(Vector A,Vector B){     return A.x*B.y-A.y*B.x; }double getDis(Point P1,Point P2){ return sqrt((P1.x-P2.x)*(P1.x-P2.x)+(P1.y-P2.y)*(P1.y-P2.y)); }int n,tot;double ans,L;Point a[maxn],ch[maxn];int Andrew(){    sort(a,a+n);    int len=0;    for(int i=0;i<=n-1;i++){        while(len>1&&dcmp(Cross(ch[len]-ch[len-1],a[i]-ch[len-1]))==-1) len--;        ch[++len]=a[i];    }    int k=len;    for(int i=n-2;i>=0;i--){        while(len>k&&dcmp(Cross(ch[len]-ch[len-1],a[i]-ch[len-1]))==-1) len--;        ch[++len]=a[i];    }    return len;}int main(){    freopen("poj1113.in","r",stdin);    freopen("poj1113.out","w",stdout);    scanf("%d%lf",&n,&L);    for(int i=0;i<=n-1;i++) scanf("%lf%lf",&a[i].x,&a[i].y);    int t=Andrew();    ans=0;    for(int i=1;i<=t-1;i++) ans+=getDis(ch[i],ch[i+1]);    printf("%.0lf\n",ans+2*3.14159*L);    return 0;}
0 0
原创粉丝点击