凸包全解

Graham-Scan法序的选取1.

选取最低点中最左的一个作为参考点      

用叉乘来排序所有点的相对位置

时间复杂度

排序O(nlog n)

扫描O(n)

总的是O(nlog n)



Graham-Scan法的特殊情况
重复点
  删除
共线点
  对于不要求求共线点的情况,可以对叉乘做严格的判定。
  对于要求求共线点的情况,没有办法简单而完美的处理:
A、B两点没有办法都加入凸包中


凸包全解凸包全解

Graham-Scan法的另外一种序

用水平序

     先按y坐标排

     y相同的按x坐标排

2次扫描

     先从第1个点即0开始到最后1个点即9得到右链

     再从最后1个点即9开始到第1个点即0,不包括已经在右链的点


处理特殊情况
   如果不要共线的点,则严格判断叉乘(即只有在左边才可以)
   如果要共线的点,则叉乘等于0即共线也认为可以
直观的理解
   很简洁,很完美~

凸包全解凸包全解

代码一: 

凸包全解
#include<math.h>

#include<stdio.h>

#include<algorithm>

using namespace std;

#define N 10005

#define PI 3.14159265

using namespace std;

struct point

{

    int x,y;

}p[N];

int dis(point p1,point p2)

{

    return ((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));

}

int xmult(point p1,point p2,point p3)

{

    return (p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y);

}

bool cmp(point p1,point p2)

{

    int k=xmult(p[0],p1,p2);

    if(k>0||!k&&dis(p[0],p1)<dis(p[0],p2))

        return true;

    return false;

}

int Graham(point *p,int n)

{

    int x=p[0].x;

    int y=p[0].y;

    int mi=0;

    for(int i=0;i<n;i++)

    {

        if(p[i].y<y || p[i].y==y&&p[i].x<x)

        {

            x=p[i].x;

            y=p[i].y;

            mi=i;

        }

    }

    point tmp=p[0];

    p[0]=p[mi];

    p[mi]=tmp;//find down left



    sort(p+1,p+n,cmp);//sort



    int top=1;

    for(int i=2;i<n;i++)

    {

        while(xmult(p[top-1],p[top],p[i])<=0 &&top>=1)

        --top;

        p[++top]=p[i];

    }

    return top+1;//number of convex

}
View Code

 

代码二:

凸包全解
#include<stdio.h>

#include<algorithm>

#include<fstream>

#include<string.h>

#include<iostream>

using namespace std;

const int MAX=550;

struct point

{

    int x;

    int y;

    int v;

    int i;

    int tmp;

} Ini[MAX],res[MAX],p[MAX];

bool flag[MAX];

int ans[MAX];

bool cmp(point A,point B)

{

    if(A.y==B.y)return A.x<B.x;

    return A.y<B.y;

}

bool cmp1(point A,point B)

{

    if(A.v>B.v)return true;

    if(A.v==B.v)

    {

        if(A.x<B.x)return true;

        if(A.x==B.x&&A.y<B.y)return true;

    }

    return false;

}

int xmult(point A,point B,point C)

{

    return (B.x-A.x)*(C.y-A.y)-(C.x-A.x)*(B.y-A.y);

}

int Graham(point *p,int n)

{

    //if (n<3)return n;

    sort(p,p+n,cmp);

    memset(flag,false,sizeof(flag));

    int i;

    int top=0;

    for(i=0; i<n; i++)

    {

        while(top>=2&&xmult(res[top-2],res[top-1],p[i])<0)

        {

            top--;

        }

        res[top++]=p[i];

        res[top-1].tmp=i;

    }

    for(i=0;i<top;i++)

        flag[res[i].tmp]=true;



    int t=top+1;

    for(i=n-2; i>=0; i--) //i>=0

    {

        while(top>=t&&xmult(res[top-2],res[top-1],p[i])<0)

            top--;

        if(!flag[i])res[top++]=p[i];

        //if(i==0)top--;

    }

    /*for(i=0; i<top; i++)

        printf("$%d %d\n",res[i].x,res[i].y);*/

    return top;

}
View Code

 

例题见下篇

你可能感兴趣的:(包)