1214:凸包模板(Andrew算法)

来源:互联网 发布:有数学题的软件 编辑:程序博客网 时间:2024/05/29 12:53

1214: [视频]【计算几何】凸包
时间限制: 1 Sec 内存限制: 128 MB
提交: 92 解决: 55
[提交][状态][讨论版]
题目描述
【题意】
在一个平面坐标系上有n个点,用笔画一个多边形,使得多边形包含这n个点(点在多边形的边上也算包含)。
求多边形的最小周长。
【输入格式】
第一行整数 n (1 <= n <= 1000),表示有n个点。
下来n行,每行两个整数x(横坐标)和y(纵坐标),表示点坐标(-10000<=x,y<=10000)。
【输出格式】
一行一个实数,即多边形的最小周长(保留4位小数)。
【样例1输入】
4
2 1
5 1
5 5
2 5
【样例1输出】
14.0000

【样例2输入】
5
2 1
5 1
3 2
5 3
2 3
【样例2输出】
10.0000

#include<iostream>#include<algorithm>#include<cmath>#include<cstdio>using namespace std;const double eps=1e-10;struct Point {double x,y;};Point p[1500],ch[1500];/*控制精度int dcmp(double x){    if (fabs(x)<eps) return 0;    else return x<0?-1:1;}*/double Cross(Point p1,Point p2,Point p)//叉乘{    int x1,y1,x2,y2;    x1=p1.x-p.x;//点坐标,转化成向量坐标    y1=p1.y-p.y;    x2=p2.x-p.x;    y2=p2.y-p.y;    return x1*y2-x2*y1;//返回叉积}//将所有的点,按x从小到大排序,x相同则按y从小到大排序bool cmp(Point a,Point b){    if (a.x!=b.x)        return a.x<b.x;    else        return a.y<b.y;}//p为输入点数组,ch为输出点数组,返回凸包顶点个数int andrew(Point *p,int n,Point *ch){    sort(p,p+n,cmp);//排序时要去掉重复的点    int m=0;    for (int i=0;i<n;i++)    {        //如果要求凸包的边上没有输入点,则将<=改成<,        //当精度要求较高时,用dcmp()函数        while(m>1&&Cross(p[i],ch[m-1],ch[m-2])<=0)            m--;        ch[m++]=p[i];    }    int k=m;    for (int i=n-2;i>=0;i--)    {        while(m>k&&Cross(p[i],ch[m-1],ch[m-2])<=0)            m--;        ch[m++]=p[i];    }    if (n>1) m--;    return m;}double getLength(Point A,Point B)//两点间的距离{    return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));}int main(){    int n;    cin>>n;    for (int i=0;i<n;i++)        cin>>p[i].x>>p[i].y;    int t=andrew(p,n,ch);    double sum=0;    for (int i=0;i<t;i++)//将每连续两个输出点的距离相加       sum+=getLength(ch[(i+1)%t],ch[i]);    printf("%.4lf",sum);    return 0;}
原创粉丝点击