HDU 1392 凸包模板题,求凸包周长

1、HDU 1392 Surround the Trees  

2、题意:就是求凸包周长

3、总结:第一次做计算几何,没办法,还是看了大牛的博客

#include<iostream>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#define F(i,a,b) for (int i=a;i<b;i++)
#define FF(i,a,b) for (int i=a;i<=b;i++)
#define mes(a,b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define LL long long
using namespace std;
const int N=110,MAX=1000100;
const double eps=1e-8;

struct Point
{
    double x,y;
}p[N],stack[N];

int isZero(double x) {      //x是否为0,还是不明白为什么要引入eps
    return (x>0?x:-x)<eps;
}

double crossProd(Point A,Point B,Point C) {     //叉积,这样写即A->B到A->C逆时针为正
    return (B.x-A.x)*(C.y-A.y)-(B.y-A.y)*(C.x-A.x);
}

double dis(Point A,Point B) {
    return sqrt((B.x-A.x)*(B.x-A.x)+(B.y-A.y)*(B.y-A.y));
}

//以最左下的点为基准点,其他各点(逆时针方向)以极角从小到大的排序规则
int cmp(const void *a,const void *b) {    //这里表示*a在*b后
    Point *c=(Point *)a, *d=(Point *)b;
    double k=crossProd(p[1],*c,*d);     //极角大小转化为求叉乘
    if(k<eps||isZero(k)&&dis(p[1],*d)<dis(p[1],*c)) return 1;
    return -1;
}

int n;
double Graham()
{
    int mi=1;
    double mx=p[1].x, my=p[1].y;
    FF(i,2,n) {     //找到最左下点
        if(my>p[i].y||my==p[i].y&&mx>p[i].x) {
            mi=i, my=p[i].y, mx=p[i].x;
        }
    }
    p[0]=p[mi], p[mi]=p[1], p[1]=p[0];  //最左下点要换到p开头,不能让它和它自己比
    qsort(p+2,n-1,sizeof(Point),cmp);
    stack[1]=p[1], stack[2]=p[2], stack[3]=p[3];
    p[n+1]=p[1];    //在结尾加最左下点为结束点,一开始没加,直接在len加了一个dis(p[1],p[n]),这样忽略了很多
    int top=3;
    for(int i=4; i<=n+1; i++) {
        //加入一个点后,向右偏拐或共线,则上一个点不在凸包内,则--top,该过程直到不向右偏拐或没有三点共线的点
        while(crossProd(stack[top-1],stack[top],p[i])<eps&&top>=3) top--;
        stack[++top]=p[i];
    }
    double len=0;
    F(i,1,top) {
        len+=dis(stack[i],stack[i+1]);
    }
    return len;
}

int main()
{
    while(scanf("%d",&n)!=EOF,n) {
        FF(i,1,n) {
            scanf("%lf%lf",&p[i].x,&p[i].y);
        }
        if(n==1) printf("0.00\n");
        else if(n==2) printf("%.2lf\n",dis(p[1],p[2]));
        else {
            printf("%.2lf\n",Graham());       //这里printf用G++11竟然输出0
        }
    }

    return 0;
}
View Code
posted @ 2016-11-02 01:00  v9fly  阅读(211)  评论(0编辑  收藏  举报