题目描述 Description
给出平面上n个点,求出这n个点形成的凸包的周长。
凸包的定义:能覆盖住这个n个点的最小凸多边形。
输入描述 Input Description
第一行一个整数n,接下来n行,每行两个整数x和y,表示一个点的坐标。
数据范围 1 <= n <= 100000
-10000<=x,y<=10000
输出描述 Output Description
一行一个实数,表示凸包周长,保留一位小数.
样例输入 Sample Input
5
0 0
2 2
0 2
2 0
1 1
样例输出 Sample Output
8.0
思路
凸包模板。。
代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=100000+5;
const double eps=1e-8;
int n;
struct Point
{
double x,y;
Point(double X=0,double Y=0){x=X;y=Y;}
};
typedef Point Point;
Point p[N],ch[N];
int dcmp(double p)
{
if (fabs(p)<=eps) return 0;
if (p>0) return 1;
else return -1;
}
Point operator +(Point a,Point b){return Point(a.x+b.x,a.y+b.y);}
Point operator -(Point a,Point b){return Point(a.x-b.x,a.y-b.y);}
Point operator *(Point a,double p){return Point(a.x*p,a.y*p);}
Point operator /(Point a,double p){return Point(a.x/p,a.y/p);}
bool operator <(Point a,Point b){return a.x<b.x;}
double Cross(Point a,Point b){return a.x*b.y-a.y*b.x;}
double DisPP(Point a,Point b)
{return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
double ConvexHull(Point *p,Point *ch,int n)
{
sort(p,p+n);
int k,sum=0;double ans=0;
for (int i=0;i<n;i++)
{
while (sum>1&&dcmp(Cross(ch[sum-1]-ch[sum-2],p[i]-ch[sum-2]))>=0)
sum--;
ch[sum++]=p[i];
}
k=sum;
for (int i=n-2;i>=0;i--)
{
while (sum>k&&dcmp(Cross(ch[sum-1]-ch[sum-2],p[i]-ch[sum-2]))>=0)
sum--;
ch[sum++]=p[i];
}
if (n>0) sum--;
for (int i=0;i<sum;i++)
ans+=DisPP(ch[i],ch[(i+1)%sum]);
return ans;
}
main()
{
scanf("%d",&n);
for (int i=0;i<n;i++)
scanf("%lf%lf",&p[i].x,&p[i].y);
printf("%.1lf",ConvexHull(p,ch,n));
return 0;
}