hdu1348 练习凸包模板使用

来源:互联网 发布:网络漂亮的小女孩图片 编辑:程序博客网 时间:2024/05/16 05:47

题意

  • 找凸包,建立一圈围墙,要求围墙上每个点,距离凸包上最近点大于等于l,问围墙的周长

思路

  • 就是求个凸包,再加上以L为半径的圆周长,看题中图很清楚
  • 貌似很多小坑点,为了节约时间的话,最好看一下discuss,基本都说清楚了~

实现

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>using namespace std;const double eps = 1e-8;const double PI = acos(-1.0);int n,l;int sgn(double x){    if(fabs(x) < eps)return 0;    if(x < 0)return -1;    else return 1;}struct Point{    double x,y;    Point(){}    Point(double _x,double _y)    {        x = _x;y = _y;    }    Point operator -(const Point &b)const    {        return Point(x - b.x,y - b.y);    }    //叉积    double operator ^(const Point &b)const    {        return x*b.y - y*b.x;    }    //点积    double operator *(const Point &b)const    {        return x*b.x + y*b.y;    }};//*两点间距离double dist(Point a,Point b){    return sqrt((a-b)*(a-b));}   /** 求凸包,Graham算法* 点的编号0~n-1* 返回凸包结果Stack[0~top-1]为凸包的编号*/const int MAXN = 1010;Point list[MAXN];int Stack[MAXN],top;//相对于list[0]的极角排序bool _cmp(Point p1,Point p2){    double tmp = (p1-list[0])^(p2-list[0]);    if(sgn(tmp) > 0)        return true;    else if(sgn(tmp) == 0 && sgn(dist(p1,list[0]) - dist(p2,list[0])) <= 0)        return true;    else         return false;}void Graham(){    Point p0;    int k = 0;    p0 = list[0];    //找最下边的一个点    for(int i = 1;i < n;i++)    {        if( (p0.y > list[i].y) || (p0.y == list[i].y && p0.x > list[i].x) )        {            p0 = list[i];            k = i;        }    }    swap(list[k],list[0]);    sort(list+1,list+n,_cmp);    if(n == 1)    {        top = 1;        Stack[0] = 0;        return;    }    if(n == 2)    {        top = 2;        Stack[0] = 0;        Stack[1] = 1;        return ;    }    Stack[0] = 0;    Stack[1] = 1;    top = 2;    for(int i = 2;i < n;i++)    {        while(top > 1 && sgn((list[Stack[top-1]]-list[Stack[top-2]])^(list[i]-list[Stack[top-2]])) <= 0)            top--;        Stack[top++] = i;    }}   int main(){    int T;    cin >> T;    while (T--){        cin>>n>>l;        for (int i=0;i<n;i++){            scanf("%lf%lf",&list[i].x,&list[i].y);        }        Graham();        double ans = l*PI*2;        for (int i=0;i<top;i++){            ans += dist(list[Stack[i]],list[Stack[(i+1)%top]]);        }        if (T != 0)            printf("%.0lf\n\n",ans);        else            printf("%.0lf\n",ans);    }    return 0;}
0 0