[POJ1113]Wall(计算几何-凸包)

题目:

我是超链接

题意:

给出一个多边形,要在外围距离r围一圈围墙,求围墙的最小长度

题解:

这个多边形肯定是个凸包啊,但是这个外围距离?!看个图冷静一下,图引自这位up
这里写图片描述
所以所求长度如图所示为凸包周长加以l为半径的圆的周长。因为绕周长一周所以为一个正圆

这里给出凸包求法:
凸包为把给定点包在内部,面积最小的凸多边形
常用Graham扫描法

  • 将点按x坐标第一关键字,y坐标第二关键字排序
  • 首先将p1,p2压入栈中
  • 判断下一个点和栈中最后一个点组成的向量是否在当前前进方向的左边(求下凸壳),如果是的话就入栈,否则弹栈

这样求出了下凸壳,再倒着做一遍就求出来了正凸壳,合起来就是完整的凸包
通过判断叉积是否=0可以控制是否有三点共线的情况
最终栈中的点就是凸包中的点
注意输入不能有重复的点
还有就是坐标不能只按照x或y坐标排序,否则处理不了所有点都在一条直线上的情况
时间复杂度O(nlogn)

一定要注意这里的边是top条,而不是top-1条

代码:

#include <algorithm>
#include <cstdio>
#include <cmath>
using namespace std;
const double eps=1e-9;
const double pi=acos(-1.0);
struct po
{
    double x,y;
    po(double X=0,double Y=0){x=X;y=Y;}
}dian[1005],stack[1005];
int dcmp(double x)
{
    if (x<=eps && x>=-eps) return 0;
    return (x>0)?1:-1;
}
int top=0,n;
double cj(po x,po y){return x.x*y.y-x.y*y.x;}
po operator -(po x,po y){return po(x.x-y.x,x.y-y.y);}
bool operator <(const po &a,const po &b){return a.x<b.x||(a.x==b.x && a.y<b.y);}
int sswr(double r)//四舍五入函数 
{
    return (r>0.0)?floor(r+0.5):ceil(r-0.5);
}
double len(po x,po y){return sqrt((x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y));}
void tb()
{
    sort(dian+1,dian+n+1);
    for (int i=1;i<=n;i++)
    {
        while (top>1 && dcmp(cj(stack[top]-stack[top-1],dian[i]-stack[top-1]))<=0) 
        top--;
        stack[++top]=dian[i];
    }
    int k=top;
    for (int i=n-1;i>=1;i--)
    {
        while (top>k && dcmp(cj(stack[top]-stack[top-1],dian[i]-stack[top-1]))<=0) top--;
        stack[++top]=dian[i];
    }
    if (n>1) top--;
}
int main()
{
    double l,x,y;
    scanf("%d%lf",&n,&l);
    for (int i=1;i<=n;i++)
    {
        scanf("%lf%lf",&x,&y);
        dian[i]=po(x,y);
    }
    tb();double ans=0;
    for (int i=1;i<=top;i++) ans+=len(stack[i],stack[i%top+1]);
    ans+=2.0*pi*l;
    printf("%d",sswr(ans));
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值