天天看點

求凸包—— graham_scan算法求凸包—— graham_scan算法

求凸包—— graham_scan算法

先按Y-X排序,在按對p0的極角排序,然後進行掃瞄

bool cmp(Point A,Point B)
{
    //return (A-vert[0])*(B-vert[0])>EPS;
    double tmp=(A-vert[0])*(B-vert[0]);
    if(tmp>EPS) return true;
    if(fabs(tmp)<EPS) return dist(A,vert[0])>dist(B,vert[0])+EPS;///極角相同時,距離遠的在前
    return false;
}

bool cmpYX(Point A,Point B)
{
    if(A.y<B.y-EPS) return true;
    if(A.y==B.y) return A.x<B.x-EPS;
    return false;
}

void graham_scan()
{
    sort(vert,vert+N,cmpYX);
    sort(vert+1,vert+N,cmp);
    top=0;
    con[top++]=vert[0];
    con[top++]=vert[1];
    for(int i=2;i<=N;i++){
        if((con[top-1]-con[top-2])*(vert[i%N]-con[top-1])<-EPS){
            top--;
            con[top++]=vert[i%N];
        }
        else if(fabs((con[top-1]-con[top-2])*(vert[i%N]-con[top-1]))<EPS){///拐向相同時,取距離遠的,舍棄距離近的
            if(dist(vert[i%N],con[top-2])>dist(con[top-1],con[top-2])+EPS){
                top--;
                con[top++]=vert[i%N];
            }
        }
        else con[top++]=vert[i%N];
        while(top>=3&&(con[top-2]-con[top-3])*(con[top-1]-con[top-2])<EPS){///這步處理是必要的
            Point tmp=con[top-1];
            top-=2;
            con[top++]=tmp;
        }
    }
}      

View Code

轉載于:https://www.cnblogs.com/--560/p/4397012.html