Wall

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1348

题意:给定多边形城堡的n个顶点,绕城堡外面建一个围墙,围住所有点,并且墙与所有点的距离至少为L,求这个墙最小的长度。

思路:如果没有"墙与所有点的距离至少为L"这个条件就只要求一个凸包,再求凸包的周长即可。墙与所有点的距离至少为L,其实只要在凸包的周长上再加一个半径为L的圆周长即可。

在vj上一直过不了,杭电oj就能过。吐了。

#include<bits/stdc++.h>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<map>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const double PI = atan(1.0)*4.;
const int maxn=200005;
struct point
{
    double x,y;
    point friend operator -(point A,point B)
    {
        return {A.x-B.x,A.y-B.y};
    }
};
struct line
{
    point x,y;
};
point p[maxn];//输入点集
point q[maxn];//凸包点集
double dis(point A,point B)//两点的距离
{
    return sqrt( (A.x-B.x)*(A.x-B.x) + (A.y-B.y)*(A.y-B.y) );
}
double chaj(point A,point B)//差积
{
    return A.x*B.y-A.y*B.x;
}
bool cmp(point A,point B)//以p[0]为起点,按差积逆时针排序
{
    double s=chaj(A-p[1],B-p[1]);
    if(s>0)
        return true;
    if(s==0)
        return dis(A,p[1])<dis(B,p[1]);
    return false;
}
double perimeter(int len)//凸包求周长
{
    double sum=0;
    for(int i=2; i<=len; i++)
        sum+=dis(q[i-1],q[i]);
    return sum+dis(q[1],q[len]);
}
int main()
{
    int t,u=0;
    cin>>t;
    while(t--)
    {
        if(u>0)
            cout<<endl;
        u++;
        int N,M;
        cin>>N>>M;
        for(int i=1; i<=N; i++)
            cin>>p[i].x>>p[i].y;
        //找到最小的点
        int K=1;
        for(int i=2; i<=N; i++)
        {
            if(p[i].y<p[K].y||(p[i].y==p[K].y&&p[i].x<p[K].x))
                K=i;
        }
        swap(p[1],p[K]);

        sort(p+2,p+1+N,cmp);

        q[1]=p[1];
        q[2]=p[2];
        int len=2;//凸包点的个数
        for(int i=3; i<=N; i++)
        {
            while(len>=2&&chaj(q[len]-q[len-1],p[i]-q[len-1])<=0)
                len--;
            q[++len]=p[i];
        }
        double sum=2*M*PI;
        printf("%.lf
",perimeter(len)+sum);//周长
    }
}
原文地址:https://www.cnblogs.com/zcb123456789/p/13781747.html