地址:
点击打开链接
这个题目还是利用了chaji的思想,小于0,则顺时针,大于零则逆时针。
代码如下:
#include<iostream>
#include<string.h>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define MAX 105
using namespace std;
struct point{
double x ;
double y ;
friend operator == (point a , point b)
{
if(a.x==b.x&&a.y==b.y)
return true ;
return false ;
}
}points[MAX];
int n ;
bool cmp(point a , point b )
{
if(a.y==b.y)
return a.x<b.x;
return a.y<b.y;
}
double judge(point a, point b , point base )
{
return (a.x - base.x)*(b.y-base.y)-(b.x-base.x)*(a.y-base.y);
}
double dis(point a,point b )
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double bk(int n)
{
if(n==1)
return 0 ;
if(n==2)
return dis(points[1],points[2]);
int ans[MAX];
ans[1]=1 ;
int index= 1;
//当它第一次转回来的时候中止
//主要思想是,每次都找到一个相对于上次的线最左侧的点,在这个点的基础上,随意再选一个点,看是否存在比这个点更加偏向右的点,这样就不必分两种情况了。
do{
index++;
int t = ans[index-1]+1;//找到上一次解决的点,+1得到下一个点
if(t>n)
t = 1 ;//注意这个地方,其实把最后的点也算了进去,也就是围城了一个圈,当把最后一个点算进去的时候才中止
for(int i = 1 ; i<= n ; i ++)
{
if(judge(points[i],points[t],points[ans[index-1]])<0)
{
t = i ;
}
}//这个地方还很巧妙的把共线的情况也算了进去,很厉害,如果共线,那么上面的if肯定进不去,就会在上一个的基础上把t原封不懂得传递过来
ans[index]=t;
}while(ans[index]!=ans[1]);
double res = 0;
for(int i = 1 ; i < index ;i++)
{
res +=dis(points[ans[i]],points[ans[i+1]]);
}
return res ;
}
int main(){
int i, j ;
while(scanf("%d",&n),n)
{
for(i = 1 ; i <= n ; i ++)
{
scanf("%lf%lf",&points[i].x,&points[i].y);
}
sort(points+1,points+1+n,cmp);
printf("%.2lf\n",bk(n));
}
}