hdu 1348 Wall (凸包模板)

/*
 题意:

 求得n个点的凸包。然后求与凸包相距l的外圈的周长。


 答案为n点的凸包周长加上半径为L的圆的周长

*/
# include <stdio.h>
# include <math.h>
# include <string.h>
# include <algorithm>
using namespace std;
# define PI acos(-1.0)
struct node
{
    int x;
    int y;
};
node a[1010],res[1010];
bool cmp(node a1,node a2)
{
    if(a1.x==a2.x)
        return a1.y<a2.y;
    return a1.x<a2.x;
}
int cross(node a1,node a2,node a3)
{
    return (a1.x-a3.x)*(a2.y-a3.y)-(a2.x-a3.x)*(a1.y-a3.y);
}
int convex(int n)//求凸包上的点
{
    int m=0,i,j,k;
    sort(a,a+n,cmp);
     //求得下凸包。逆时针
    //已知凸包点m个。假设新增加点为i。则向量(m-2,i)必然要在(m-2,m-1)的逆时针方向才符合凸包的性质
    //若不成立。则m-1点不在凸包上。
    for(i=0;i<n;i++)
    {
        while(m>1&&cross(res[m-1],a[i],res[m-2])<=0)
            m--;
        res[m++]=a[i];
    }
    k=m;
    //求得上凸包
    for(i=n-2;i>=0;i--)
    {
        while(m>k&&cross(res[m-1],a[i],res[m-2])<=0)
            m--;
        res[m++]=a[i];
    }
    if(n>1)
        m--;
    return m;
}
double length(node a1,node a2)
{
    return sqrt(1.0*(a1.x-a2.x)*(a1.x-a2.x)+(a1.y-a2.y)*(a1.y-a2.y));
}
int main()
{
    int t,n,i,L,m;
    while(~scanf("%d",&t))
    {
        while(t--)
        {
            scanf("%d%d",&n,&L);
            for(i=0;i<n;i++)
                scanf("%d%d",&a[i].x,&a[i].y);
            m=convex(n);
            double ans=0;
            for(i=1;i<m;i++)
                ans+=length(res[i],res[i-1]);
            ans+=length(res[0],res[m-1]);
            ans+=2*PI*L;
            printf("%.0lf
",ans);
            if(t)
                printf("
");
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/yjbjingcha/p/6807737.html