凸包问题

  研究一下,学习了个Graham-Scan求凸包的方法,主要用了排序,栈,还有叉积。下面是求周长和面积的模板。

#include <cstdio>
#include <cmath>
#include <algorithm>
#define FOR(i,x,y) for(int i=x;i<=y;++i)
using namespace std;
const double eps=1e-10;
int n,top,location;
double len,area,temp,px,py;
struct k
{
    double x,y;
}result[110],tree[110];// 模拟堆栈S,保存凸包上的点
double dis(k p1,k p2)
{
    return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}
double mul(k p1,k p2,k p3) // 叉积
{
    return ((p2.x-p1.x)*(p3.y-p1.y)-(p2.y-p1.y)*(p3.x-p1.x));
}
bool cmp(k a,k b)
{
    double m;
    m=mul(tree[0],a,b);
    if(m<0) return 0;
    else if(m==0&&(dis(tree[0],a)<dis(tree[0],b))) return 0;
    return 1;
}
void Tubao()
{
    top=2;
    FOR(i,0,2)
    {
        result[i].x=tree[i].x;
        result[i].y=tree[i].y;
    }
    FOR(i,3,n)
    {
        while(mul(result[top-1],result[top],tree[i])<=0) --top;//出栈
        result[top+1].x=tree[i].x;
        result[top+1].y=tree[i].y;
        ++top;
    }
}
int main ()
{
    while(scanf("%d",&n)!=EOF&&n)
    {
        py=0x3f3f3f; len=0.0; area=0.0;
        FOR(i,0,n-1) scanf("%lf%lf",&tree[i].x,&tree[i].y);
        if(n==1)
        {
            printf("0.00\n");
            continue;
        }
        else if(n==2)
        {
            printf("%.2f\n",dis(tree[0],tree[1]));
            continue;
        }
        FOR(i,0,n-1)//找出y最小的点
        {
            if(tree[i].y<py)
            {
                px=tree[i].x;
                py=tree[i].y;
                location=i;
            }
            else if(tree[i].y-py<eps&&tree[i].x<px)
            {
                px=tree[i].x;
                py=tree[i].y;
                location=i;
            }
        }
        temp=tree[0].x;//把y最小的移到tree[0]
        tree[0].x=tree[location].x;
        tree[location].x=temp;
        temp=tree[0].y;
        tree[0].y=tree[location].y;
        tree[location].y=temp;
        sort(tree+1,tree+n,cmp);
        tree[n].x=tree[0].x;
        tree[n].y=tree[0].y;
        Tubao();
        FOR(i,0,top-1) len+=dis(result[i],result[i+1]);
        FOR(i,0,top-1) area+=mul(result[0],result[i],result[i+1]);
        area=fabs(area)/2;
        printf("%.2f\n%.2f",len,area);
    }
    return 0 ;
}

  

你可能感兴趣的:(凸包问题)