这道题是一道凸包模板题,但是这个模板着实有点数学化hh,这种题喜欢卡精度(我不会) 现在开始边代码边解释

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
const double eps=1e-8;//设置精度,本人也不知道怎么来的
struct point//设置点结构体
{
	double x,y;//横纵坐标
    point(double a=0,double b=0):x(a),y(b){}//构造函数,如果不传参则x,y为0;
    point operator +(const point &A)const//重载+,直接进行两点相加
    {
        return point(x+A.x,y+A.y);
    }
    point operator -(const point &A)const//重载-,直接进行两点坐标相减
    {
        return point(x-A.x,y-A.y);
    }
    double operator *(const point &A)const//重载*,表示两点的点积
    {
        return x*A.x+y*A.y;
    }
    double operator ^(const point &A)const//重载^,表示两点的叉积
    {
        return x*A.y-y*A.x;
    }

};
struct line//设置线结构体
{
    point s,e;
    line(){}
    line(point a,point b):s(a),e(b){}
    pair<int,point>operator &(const line &b)const
    {
        point res=s;
        if(sgn((s-e)^(b.s-b.e))==0)
        {
            if(sgn((s-b.s)^(b.s-b.e))==0)
            {
                return make_pair(0,res);
            }
            else return make_pair(1,res);
        }
        double t=((s-b.s)^(b.s-b.e))/((s-e)^(b.s-b.e));
        res.x+=(e.x-s.x)*t;
        res.y+=(e.y-s.y)*t;
        return make_pair(2,res);
    }
};
double dist(point a,point b)
{
    return sqrt((a-b)*(a-b));
}
const int MAXN=1010;
point mylist[MAXN];
int mystack[MAXN],top;
bool cmp(point p1,point p2)//排序时的比较函数,按照角度来的,角度大小由叉积判断
{
    double tmp=(p1-mylist[0])^(p2-mylist[0]);
    if(sgn(tmp)>0)return true;
    else if(sgn(tmp)==0&&sgn(dist(p1,mylist[0])-dist(p2,mylist[0]))<=0)
        return true;
    else return false;
}
void Gramham(int n)
{
	point p=mylist[0];//用来找到相对起始点
    int k=0;//用来记录起始点的实际读入位置
    for(int i=1;i<n;i++)
    {
    	if(p.y>mylist[i].y||(p.y==mylist[i].y&&sgn(p.x-mylist[i].x)>=0)
        {
        	p=mylist[i];
            k=i;
        }
    }
    swap(mylist[k],mylist[0]);//起始点不需要排序
    sort(mylist+1.mylist+n,cmp);
    if(n==1)//只有一个点,那么栈中只有一个元素且该元素是一个点
    {
    	top=1;
        mystack[0]=0;
        return;
    }
    else if(n==2)//如果有两个点,那么还是同样道理
    {
    	top=2;
        mystack[0]=0;
        mystack[1]=1;
        return;
    }
    else
    {
    	mystack[0]=0;
        mystack[1]=1;
        top=2;
        for(int i=2;i<n;i++)
        {
        	while(top>1&&sgn((mylist[mystack[top-1]-mylist[mystack[top-2])^(mylist[i]-mylist[mystack[top-2]])<=0)top--;//需要保证栈中至少有一个元素并且栈顶的前两个元素与栈顶元素和要新加进来的元素保证向左偏
            mystack[top++]=i;
        }
    }
}
int main()
{
    int n;
    while(cin>>n,n)
    {
        for(int i=0;i<n;i++)
        {
            cin>>mylist[i].x>>mylist[i].y;//mylist存储点
        }
        double ans;
        if(n==1)
        {
            ans=0.0;
            printf("%.2lf\n",ans);
            continue;
        }
        if(n==2)
        {
            ans=dist(mylist[0],mylist[1]);
            printf("%.2lf\n",ans);
            continue;
        }
        Graham(n);
        ans=dist(mylist[mystack[top-1]],mylist[mystack[0]]);
        for(int i=0;i<top-1;i++)
            ans+=dist(mylist[mystack[i]],mylist[mystack[i+1]]);
        printf("%.2lf\n",ans);
    }
    return 0;
}