这道题是一道最基本的求凸包的题。
极角排序(a,b,c),然后使用栈来求
按极角排序的顺序对于每个点c,判断:1. b在线段ac内侧,则ab出栈,ac进栈 2. b在线段ac外侧,则保留原来在栈内的ab,并将bc入栈
如果不判断最后两个点是否使其成为一个凸包,则可以按逆时针顺时针方向各做一次
/*
ID:xsy97051
LANG:C++
PROG:fc
*/
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
using namespace std;
#define maxn 10010
int n,top;
struct Point{double x,y;};
Point p[maxn],stack[maxn];
//............................................栈
void stackempty() { top=0; }
void pop() { top--; }
void push(Point x) { stack[++top]=x; }
double crossmul(Point p1,Point p2)
{
return (p1.x*p2.y-p1.y*p2.x);
}
double dis(Point p1,Point p2)
{
return(sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y)));
}
Point vectordec(Point p1,Point p2)
{
Point pi;
pi.x=p1.x-p2.x;
pi.y=p1.y-p2.y;
return pi;
}
double dcmp(double a1,double a2)
{
if(fabs(a1-a2)<=(1e-7)) return 0;
return(a1-a2);
}
//...............................................极角排序
int cmp(const void *x1,const void *x2)
{
Point p1,p2;
p1=*((Point *)x1);
p2=*((Point *)x2);
if(dcmp(p1.y,p2.y))
{
if(p1.y-p2.y>0)return 1;
else
if(p1.y-p2.y<0)return -1;
else return 0;
}
else
{
if(p1.x-p2.x>0)return 1;
else
if(p1.x-p2.x<0)return -1;
else return 0;
}
}
void work()
{
int i;
double sum=0;
Point tmp;
qsort(&p[1],n,sizeof(Point),cmp);
//左
stackempty();
push(p[1]);
i=2;
while(i<=n)
{
Point temp1=vectordec(stack[top],stack[top-1]);
Point temp2=vectordec(p[i],stack[top]);
if(top==1||dcmp(crossmul(temp1,temp2),0)>=0)
{
sum+=dis(p[i],stack[top]);
push(p[i]); i++;
}
else
{
sum-=dis(stack[top],stack[top-1]);
pop();
}
}
//右
stackempty();
push(p[n]);
i=n-1;
while(i>=1)
{
Point temp1=vectordec(stack[top],stack[top-1]);
Point temp2=vectordec(p[i],stack[top]);
if(top==1||dcmp(crossmul(temp1,temp2),0)>=0)
{
sum+=dis(p[i],stack[top]);
push(p[i]); i--;
}
else
{
sum-=dis(stack[top],stack[top-1]);
pop();
}
}
printf("%.2lf\n",sum);
}
int main()
{
freopen("fc.in","r",stdin);
freopen("fc.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%lf%lf",&p[i].x,&p[i].y);
work();
return 0;
}