POJ1113——WALL 凸包

调了两个小时(吐
poj1113
凸包有毒啊???
闲的蛋疼用了一个函数叫atan2
然而这个东西用法有点神奇。。是用来求极角的
atan2(y,x) 注意是y,x 得到的是(x,y)点对对于0,0的弧度!注意是弧度!
弧度转化角度:

#define atan2(x,y) atan2(x,y)*180/3.1415926535

当然其实这题。。不转化角度也没关系,显然弧度与角度是增函数的关系没毛病啊

凸包过程:
1、找到点中左下角(先下,再左)的点,以它为原点
2、求出所有点的极角
3、按照极角排序
4、维护一个栈,保持凸多边形性质,即新加入的点不能在原先的边的右侧
5、完了。

这里我判断是否在右侧是用叉积(因为刚学)
其实也可以直接用解析式判断,具体不细讲

接下来说一下这个题的几个坑点….

1、角度要开double=_=
好吧这个是我傻逼了
2、共线情况要先按纵坐标从小到大排序,再按横坐标从大到小排序
画图理解一下就行,横坐标。。实际上是一样的。。。。

CODE:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#include<string>
#include<map>
#include<cstring>
#include<vector>
#define inf 1e9
#define ll long long
#define atan2(x,y) atan2(x,y)*180/3.1415926535
#define For(i,j,k) for(ll i=j;i<=k;i++)
#define Dow(i,j,k) for(ll i=k;i>=j;i--)
using namespace std;
struct point
{
    int  x,y;
    double aph;
}a[2001];
int n;
int d;
int sta[5001];
inline bool cmp(point t1,point t2)
{
    if(t1.aph!=t2.aph)return t1.aph<t2.aph;
    if(t1.y!=t2.y) t1.y<t2.y;
    return t1.x<t2.x;
}
inline double sqr(double x)
{
    return x*x;
}
int main()
{
    scanf("%d%d",&n,&d);
    int t=0;
    a[0].y=1e9;
    For(i,1,n)
    {
        scanf("%d%d",&a[i].x,&a[i].y);
        if(a[i].y<a[t].y||(a[i].y==a[t].y&&a[i].x<a[t].x))
            t=i;
    }
    swap(a[t],a[1]);
    For(i,2,n)  a[i].x-=a[1].x,a[i].y-=a[1].y;
    a[1].x=a[1].y=0;
    For(i,1,n)
        a[i].aph=atan2(a[i].y,a[i].x);
    sort(a+2,a+n+1,cmp);
    sta[1]=1;sta[2]=2;
    int top=2;
    For(i,3,n)  
    {
        while(1)
        {
        int p1=sta[top],p2=sta[top-1];
        int S=(a[p1].x-a[p2].x)*(a[i].y-a[p2].y)-(a[i].x-a[p2].x)*(a[p1].y-a[p2].y);
        if(S<0) 
            top--;else break;
        }
        sta[++top]=i; 
    }
    double  ans=0;
    For(i,1,top)
        ans+=sqrt(sqr((double)a[sta[i%top+1]].x-(double)a[sta[i]].x)+sqr((double)a[sta[i%top+1]].y-(double)a[sta[i]].y));

    ans+=3.1415926*(double)d*2.00;
    printf("%.0f\n",ans);
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值