您的位置:首页 > 其它

CodeVS1298 凸包周长 解题报告【计算几何】【凸包】

2017-08-20 20:25 513 查看
题目描述 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

解题报告

首先我们要解决存储问题,由于凸包的周长需要算第一个点和最后一个点间的距离,所以不能用vector存储,只能用数组来。

代码如下:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cstdlib>
#define NAME ""
#define Point Vector
using namespace std;
const double eps=1e-8;
const int N=100000;
struct Vector
{
double x,y;
double len(){return sqrt(x*x+y*y);}
double ang(){return atan2(y,x);}
Vector(int a=.0,int b=.0):x(a),y(b){}
Vector operator+(const Vector &s)const{return Vector(x+s.x,y+s.y);}
Vector operator-(const Vector &s)const{return Vector(x-s.x,y-s.y);}
Vector operator*(int s)const{return Vector(x*s,y*s);}
Vector operator/(int s)const{return Vector(x/s,y/s);}
bool operator<(const Point &s)const
{
if(s.x==x)return y<s.y;
else return x<s.x;
}
}p[N+5],ch[N+5];
double dis(Point a,Point b)
{
Point c=b-a;
return c.len();
}
double cross(Vector a,Vector b){return a.x*b.y-a.y*b.x;}//向量叉积
int sign(double a){return a>eps?1:(a<-eps?-1:0);}
bool onleft(Point a,Point b,Point p)
{
return sign(cross(b-a,p-a))>0;
}
double ComvexHull(Point* p,int n,Point* ch)
{
sort(p+1,p+n+1);
int m=0;
for(int i=1;i<=n;++i)
{
while(m>1&&cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0) m--;
ch[m++]=p[i];
}
int k=m;
for(int i=n-1;i>=1;--i)
{
while(m>k&&cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0) m--;
ch[m++]=p[i];
}
if(n>1) m--;
double c=dis(ch[1],ch[m]);
for(int i=1;i<m;++i) c+=dis(ch[i],ch[i+1]);
return c;
}
int n;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
double x,y;
scanf("%lf%lf",&x,&y);
p[i]=Point(x,y);
}
printf("%.1lf",ComvexHull(p,n,ch));
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: