#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int Max = 1100;

struct Point
{
    int x;
    int y;
};
int num;
Point p[Max];   ///原始点集
Point ch[Max];  ///凸包点集

///p0p1叉乘p0p2
int xmult(const Point &p0, const Point &p1, const Point &p2)
{
    return (p1.x-p0.x)*(p2.y-p0.y) - (p2.x-p0.x)*(p1.y-p0.y);
}

double dis(const Point &a, const Point &b)
{
    return sqrt((double)(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

///逆时针顺序把极角排序
bool cmp(const Point &a, const Point &b)
{
    int ret = xmult(p[0],a,b);
    if(ret>0)
        return true;
    if(ret==0&&dis(p[0],a)<dis(p[0],b))//保留凸包上的点,共线取最近
        return true;
    return false;
}
//如果我们只要求保留极点而去除在边上的点

//我们只需在取外侧的点的时候 碰到共线的点取最远的

//相反 如果我们要保留所有在边上的点我们只需要在共线的点中取最近的

/**
p: 原始点序列
n: 原始点的个数
ch: 栈,用来保存凸包上的点
top: 凸包上点的个数
*/
void Graham(Point *p, int n, Point *ch, int &top)
{
    int i,k=0;
    for(i=1; i < n; i++)//取纵坐标最小的点,纵坐标相同取横坐标最小,此点必在凸包上
    {
        if(p[k].y>p[i].y || ((p[k].y==p[i].y)&&p[k].x>p[i].x))
            k = i;
    }
    swap(p[k],p[0]);//p[0]为此点
    sort(p+1,p+n,cmp);//
    top = 0;
    ch[top++] = p[0];
    ch[top++] = p[1];
    ch[top++] = p[2];
    for(i = 3; i < n; ch[top++]=p[i++])
        while(top>=2 && xmult(ch[top-2],ch[top-1],p[i])<0)    ///是否向左
            top--;
}

int main()
{
    //freopen("C:\\Users\\Sky\\Desktop\\1.in","r",stdin);
    int i;
    int n,l;
    int t;
    while(scanf("%d",&n),n)
    {
        for(i = 0; i < n; i++)
            scanf("%d %d",&p[i].x,&p[i].y);
        if(n==1)
        {
            printf("0.00\n");
            continue;
        }
        else if(n==2)
        {
            printf("%.2lf\n",dis(p[0],p[1]));
            continue;
        }
        Graham(p,n,ch,num);
        double result=0.0;
        for(i = 0; i < num-1; i++)
            result += dis(ch[i],ch[i+1]);
        result += dis(ch[0],ch[num-1]);
        printf("%.2lf\n",result);
    }
    return 0;
}
View Code

相关文章:

  • 2021-06-12
  • 2022-02-17
  • 2022-12-23
  • 2021-11-27
  • 2022-12-23
  • 2021-12-20
  • 2021-04-18
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2021-10-09
  • 2021-10-02
  • 2022-12-23
  • 2021-05-23
  • 2021-08-08
相关资源
相似解决方案