凸包_HDU1348

这可以说是一个凸包的模板题,之前的Graham扫描算法中还不是很懂其中叉积的作用,今天正好遇到这个题,那么就把前面的模板整理了一下:凸包判断_Graham扫描算法模板

题目意思

给出一个有N个点的多边形,在距离多边形为L的地方把多边形包围起来,计算包围起来需要的长度为多少?

那么这个题很明显就是一个凸包问题,那么处理拐角的地方,我们外面包围的长度和凸包的周长是相同的,我们将左右的拐角放在一起就是一个半径为L的圆,那么最终的周长也是可以求得的了

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define INF 0x3f3f3f3f

using namespace std;
const int MAXN = 1100;
const double PI = 3.1415926535;
int n,l;
struct Point
{
    int x,y;
}p[MAXN],c[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));
}
int mulit(Point p0,Point p1,Point p2)
{
    return (p1.x - p0.x)*(p2.y - p0.y) - (p1.y - p0.y) * (p2.x - p0.x);
}
bool cmp(Point a,Point b)
{
    int x = mulit(p[0],a,b);
    if(x > 0 || (x == 0 && dis(p[0],a) < dis(p[0],b)) )return true;
    return false;
}

int Graham()
{
    int k = 0;
    for(int 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;
    swap(p[k],p[0]);
    sort(p+1,p+n,cmp);
    int tot = 1;
    c[0] = p[0],c[1] = p[1];
    for(int i = 2;i < n;i ++)
    {
        while(tot && mulit(c[tot-1],c[tot],p[i]) <= 0) tot--;
        c[++tot] = p[i];
    }
    return tot;
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&l);
        for(int i = 0;i < n;i ++)
            scanf("%d%d",&p[i].x,&p[i].y);
        int tot = Graham();
        double ans = 0;
        for(int i =0 ;i <= tot;i ++)
            ans += dis(c[i],c[(i+1)%(tot+1)]);
        ans += l*2*PI;
        printf("%.0lf\n",ans);
        if(T!=0) printf("\n");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/li1615882553/article/details/80369378