hdu 1392(凸包)

 

传送门:Surround the Trees

题意:求凸包的周长。

分析:凸包模板题,先按极角排好序后,然后根据叉积正负确定凸包。

#include <stdio.h>
#include <math.h>
#include <algorithm>
#include <string.h>
#include <math.h>
using namespace std;

const double eps = 1e-8;
const int N = 110;
int sgn(double x)
{
    if(fabs(x) < eps)return 0;
    if(x < 0)return -1;
    else return 1;
}
struct Point
{
    double x,y;
    Point(){}
    Point(double _x,double _y)
    {
        x = _x;y = _y;
    }
    Point operator -(const Point &b)const
    {
        return Point(x - b.x,y - b.y);
    }
    //叉积
    double operator ^(const Point &b)const
    {
        return x*b.y - y*b.x;
    }
    //点积
    double operator *(const Point &b)const
    {
        return x*b.x + y*b.y;
    }
};
double dist(Point a,Point b)
{
    return sqrt((a-b)*(a-b));
}
Point p[N];
int Stack[N],top;
bool cmp(Point p1,Point p2)
{
    double tmp=(p1-p[0])^(p2-p[0]);
    if(sgn(tmp)==0)return sgn(dist(p[0],p1)-dist(p[0],p2))<=0;
    return sgn(tmp)>0;
}
void Graham(int n)
{
    sort(p+1,p+n,cmp);
    Stack[0]=0;
    Stack[1]=1;
    top=2;
    for(int i=2;i<n;i++)
    {
        while(top>1&&sgn((p[Stack[top-1]]-p[Stack[top-2]])^(p[i]-p[Stack[top-2]]))<=0)top--;
        Stack[top++]=i;
    }
}
int main()
{
    int n;
    while(scanf("%d",&n),n)
    {
        for(int i=0;i<n;i++)
        {
            scanf("%lf%lf",&p[i].x,&p[i].y);
            if(p[i].y<p[0].y||p[i].y==p[0].y&&p[i].x<p[0].x)
                swap(p[0],p[i]);
        }
        if(n==1)puts("0.00");
        else if(n==2)printf("%.2lf\n",dist(p[0],p[1]));
        else
        {
            Graham(n);
            double ans=0;
            for(int i=0;i<top;i++)
                ans+=dist(p[Stack[i]],p[Stack[(i+1)%top]]);
            printf("%.2lf\n",ans);
        }
    }
    return 0;
}
View Code

 

posted on 2015-03-13 23:56  lienus  阅读(140)  评论(0编辑  收藏  举报

导航