POJ 1113 入门凸包

自己的第一法凸包
思路就是,建立凸包,求凸包周长加上圆的周长,主要练模版

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
const double eps=1e-8;
const double PI=acos(-1);
const int maxn=1000+10;
int N,L;
int top;
using namespace std;
int sgn(double x){
    if(fabs(x)<eps)
        return 0;
    if(x>0)
        return 1;
    if(x<0)
        return -1;
}
struct point{
    int x,y;
    point() {}
    point(int _x,int _y){
        x=_x;
        y=_y;
    }
};
typedef point vector;
vector operator + (vector A,vector B){
    return point(A.x+B.x,A.y+B.y);
}
vector operator - (point A,point B){
    return point(A.x-B.x,A.y-B.y);
}
int operator ^ (vector A,vector B){
    return A.x*B.y-A.y*B.x;
}
int operator * (vector A,vector B){
    return A.x*B.x+A.y*B.y;
}
bool operator < (vector A,vector B){
    return A.x<B.x || A.x==B.x && A.y<B.y;
}
bool operator == (point a,point b){
    return sgn(a.x-b.x)==0 && sgn(a.y-b.y)==0;
}
double dis(point a,point b){
    return hypot(a.x-b.x,a.y-b.y);
}
struct convex{
    int n;
    point p[maxn];
};
convex t;
point p[maxn];
bool cmp(point a,point b){ //极角排序函数
        int d=(a-p[0])^(b-p[0]);
        if(d==0&&sgn(dis(a,p[0])-dis(b,p[0])) < 0 || d>0)//共线时取较近的点
            return true;
        return false;
}
void init(){   //找到初始点
    for(int i=0;i<N;i++)
        if(p[i]<p[0])
            swap(p[i],p[0]);
}
void graham(int n)   //graham-scan
{
    n=N;
    if(n==1){
        top=1;
        t.p[0]=p[0];
    }
    else if(n==2){
        top=2;
        t.p[0]=p[0];t.p[1]=p[1];
        if(t.p[0]==t.p[1])
            top--;
    }
    else{
        t.p[0]=p[0];t.p[1]=p[1];
        top=2;
        for(int i=2;i<n;i++){
            while(top>1 && sgn((t.p[top-1]-t.p[top-2])^(p[i]-t.p[top-2])) <= 0)
                  top--;
            t.p[top]=p[i];
            top++;
        }
    }
}
double solve(){
    double res=2*PI*L;
    init();
    sort(p+1,p+N,cmp);
    graham(N);
    /*for(int i=0;i<top;i++)
        printf("(%d,%d)\n",t.p[i].x,t.p[i].y);*/
    for(int i=0;i<top;i++)
        res+=dis(t.p[i],t.p[(i+1)%top]);
    return res;
}
int main(){
    //freopen("input.txt","r",stdin);
    while(~scanf("%d%d",&N,&L)){
        double res;
        for(int i=0;i<N;i++){
            int x,y;
            scanf("%d%d",&x,&y);
            p[i]=point(x,y);
        }
        res=solve();
        printf("%d\n",int(res+0.5));
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值