计算几何 ( 凸包 )——Wall ( HDU 1248 )

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

  • 分析:
    给出N个点,求距离这N个点围成的多边形距离为L的围墙的周长。可以得出,这个周长就是多边形周长加上一个圆的周长。多半形周长可以先求出凸包点集,然后依次累加距离即可。然后这个题需要注意输出格式!最后一个输出数据不用加两个换行!!!

  • 题解:
    1.求凸包:

int cmp(point a, point b)  //水平排序
{
    if(a.x==b.x)return a.y<b.y;
        return a.x<b.x;
}

int convex(int n, point P[], point res[])//n为总点数,P 为点集,res为输出凸包上点的点集
{
    sort(P, P+n,cmp);
    int m=0,i,j,k;
    //求得下凸包,逆时针
    //已知凸包点m个,如果新加入点为i,则向量(m-2,i)必定要在(m-2,m-1)的逆时针方向才符合凸包的性质
    //若不成立,则m-1点不在凸包上。
    for(i=0;i<n;i++)
    {
        while(m>1&&multiply(res[m-1], P[i], res[m-2])<=0)
            m--;
        res[m++]=P[i];
    }
    k=m;
    //求得上凸包
    for(i=n-2;i>=0;i--)
    {
        while(m>k&&multiply(res[m-1],P[i],res[m-2])<=0)m--;
        res[m++]=P[i];
    }
    if(n>1) m--;//起始点重复。
    return m;
}
  • AC代码:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
using namespace std;
const double PI  = 3.14159265;

int N, L;

struct point
{
    double x;
    double y;
}P[1234],res[1234];

int cmp(point a, point b)  //水平排序
{
    if(a.x==b.x)return a.y<b.y;
        return a.x<b.x;
}

double multiply(point a, point b,point c)//向量积
{
    return (a.x-c.x)*(b.y-c.y)-(b.x-c.x)*(a.y-c.y);
}

int convex(int n, point P[], point res[])//n为总点数,P 为点集,res为输出凸包上点的点集
{
    sort(P, P+n,cmp);
    int m=0,i,j,k;
    //求得下凸包,逆时针
    //已知凸包点m个,如果新加入点为i,则向量(m-2,i)必定要在(m-2,m-1)的逆时针方向才符合凸包的性质
    //若不成立,则m-1点不在凸包上。
    for(i=0;i<n;i++)
    {
        while(m>1&&multiply(res[m-1], P[i], res[m-2])<=0)
            m--;
        res[m++]=P[i];
    }
    k=m;
    //求得上凸包
    for(i=n-2;i>=0;i--)
    {
        while(m>k&&multiply(res[m-1],P[i],res[m-2])<=0)m--;
        res[m++]=P[i];
    }
    if(n>1) m--;//起始点重复。
    return m;
}

double dist(point p1,point p2)                // 返回两点之间欧氏距离
{
 return sqrt( (p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y) )  ;
}


int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d%d", &N, &L);
        int t = 0;
        while(t<N)
        {
            scanf("%lf%lf", &P[t].x, &P[t].y);
            t++;
        }
        int len = convex(N, P, res);
        double Length = PI * L * 2;
        for(int i=0;i<len-1;i++)
        {
            Length += dist(res[i], res[i+1]);
        }
        Length += dist(res[len-1], res[0]);
        printf("%.0lf\n", Length); //printf自带四舍五入
        if(T) cout << endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值