ZJU1453 Surround the Trees - 计算几何 经典凸包

 题目大意:

给出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;
}

你可能感兴趣的:(算法,struct,ini,math.h)