题目大意:
给出n棵树的坐标,求最短用多长的绳子能把所有树围起来。(n<100)
分析:
典型的凸包问题。
首先用Graham算法求出点集的凸包,然后依次计算凸包上两点间距离即可。
贴代码:
/*
ZJU1453 Surround the Trees
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define N 105
typedef struct{
int x,y;
}Point;
Point p[N];
Point ch[N];
int n;
int mul(Point p1,Point p2,Point p0){
return (p1.x-p0.x)*(p2.y-p0.y) - (p2.x-p0.x)*(p1.y-p0.y);
}
int dis(Point p,Point q){
return (p.x-q.x)*(p.x-q.x) + (p.y-q.y)*(p.y-q.y);
}
int cmp(const void *e1,const void *e2){
Point *a,*b;
a=(Point*)e1;
b=(Point*)e2;
int mu=mul(*a,*b,p[0]);
if(mu>0) return -1;
if((mu==0)&&(dis(p[0],*a)<dis(p[0],*b))) return -1;
return 1;
}
int Graham(){
int i,j,k,top;
Point tmp;
k=0; top=2;
if(n<=3){
for(i=0;i<4;i++) ch[i]=p[i];
return n;
}
for(i=1;i<n;i++)
if((p[i].y<p[k].y)||((p[i].y==p[k].y)&&(p[i].x>p[k].x))) k=i;
tmp=p[0]; p[0]=p[k]; p[k]=tmp;
qsort(p+1,n-1,sizeof(Point),cmp);
ch[0]=p[0]; ch[1]=p[1]; ch[2]=p[2];
for(i=3;i<n;i++){
if((i+1<n)&&(mul(p[i],p[i+1],p[0])==0)) continue;
while(mul(p[i],ch[top],ch[top-1])>=1) top--;
ch[++top]=p[i];
}
return ++top;
}
double length(Point p[],int n){
int i,j,k;
double s=0.;
if(n==1) return 0.;
for(i=0;i<n;i++){
j=i+1<n?i+1:0;
s+=sqrt(dis(p[i],p[j]));
}
return s;
}
int main()
{
int i,j,k,m;
double ans;
while(scanf("%d",&n),n){
//input
for(i=0;i<n;i++)
scanf("%d%d",&p[i].x,&p[i].y);
//Graham
m=Graham();
ans=length(ch,m);
printf("%.2lf/n",ans);
}
return 0;
}