基础的计算几何题,求一个周长最小的,覆盖所有点集的多边形。明显是求凸包。求凸包先要做极角排序,这里不要用斜率做,否则会带来很多麻烦。用叉乘法,分别将两点,B,C与最低点A连接,若AB×AC<0,则B的极角大于C。这里说一下等于0的情况,也就是A,B,C共线,则令离A远的点极角大。然后就是入栈搜索,这一段略。最后,就是求多边形周长。特别的,若入栈使没有拐弯过,即所有点共线,要除2。
一下是程序:
#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;
int n;
struct point
{
int x;
int y;
point()
{
x=0;y=0;
}
};
int check(point a,point b,point c)
{
int x1,x2,y1,y2,r;
x1=b.x-a.x;
x2=c.x-a.x;
y1=b.y-a.y;
y2=c.y-a.y;
r=x1*y2-x2*y1;
return r;
}
double dis(point a,point b)
{
double r;
r=(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
r=sqrt(r);
return r;
}
void anglesort(point* a)
{
int i,j,r,flag;
for (i=1;i<n-1;i++)
for (j=i+1;j<n;j++)
{
flag=0;
r=check(a[0],a[i],a[j]);
if (r<0) flag=1;
else if (r==0)
{
if (dis(a[0],a[i])>dis(a[0],a[j])) flag=1;
}
if (flag)
{
point tmp=a[i];
a[i]=a[j];
a[j]=tmp;
}
}
}
void input(point* a)
{
int mi,i,mmin=10e8;
for (i=0;i<n;i++)
{
scanf("%d%d",&a[i].x,&a[i].y);
if (a[i].y<mmin)
{
mmin=a[i].y;
mi=i;
}
}
point tmp=a[mi];
a[mi]=a[0];
a[0]=tmp;
a[n]=a[0];
}
void making(point* a,int* b,double &r)
{
b[0]=0;b[1]=1;
int top=1,s=2,t,i,flag=1;
while (true)
{
int x=b[top-1],y=b[top];
t=check(a[x],a[y],a[s]);
if (t>=0)
{
if (t!=0) flag=0;
b[++top]=s;
s++;
}
else top--;
if (b[top]==n) break;
}
for (i=0;i<top;i++)
r+=dis(a[b[i]],a[b[i+1]]);
if (flag) r/=2.0;
}
int main()
{
int i,j;
double r;
while (scanf("%d",&n))
{
r=0;
if (n==0) break;
point* a=new point[n+10];
input(a);
if (n==2) r=dis(a[0],a[1]);
else
{
r=0;
anglesort(a);
int* b=new int[n+10];
memset(b,0,sizeof(b));
making(a,b,r);
delete []b;
}
cout<<fixed<<setprecision(2)<<r<<endl;
delete []a;
}
return 0;
}