zoukankan      html  css  js  c++  java
  • poj 1113 Wall(凸包)

    题意:建围墙将n个点围起来,围墙与点的距离不小于L,求围墙长度;

    思路:凸包周长+L为半径的圆周长;凸包即为覆盖一个点集所有点的最小区域;

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    const double epsi=1e-10;
    const double pi=acos(-1.0);
    const int maxn=10005;
    struct point{
        double x,y;
        point(){}
        point(double xx,double yy):x(xx),y(yy){}
        point operator -(const point &op2)const{
            return point(x-op2.x,y-op2.y);
        }
        double operator ^(const point &op2) const{ //两个点向量的叉积
            return x*op2.y-y*op2.x;
        }
    };
    inline int sign(const double &x){
        if(x>epsi) return 1;
        if(x<-epsi) return -1;
        return 0;
    }
    inline double sqr(const double &x){
        return x*x;
    }
    inline double mul(const point &p0,const point &p1,const point &p2){
        return (p1-p0)^(p2-p0);
    }
    inline double dis2(const point &p0,const point &p1){
        return sqr(p0.x-p1.x)+sqr(p0.y-p1.y);
    }
    inline double dis(const point &p0,const point &p1){
        return sqrt(dis2(p0,p1));
    }
    int n,l;        //n个顶点,最近距离为l
    point p[maxn],convex_hull;  //多边形顶点序列为p[],最低位置的点为convex_hull
    inline bool cmp(const point &a,const point &b){ //相对最低点,各点极角从小到大,距离从近到远排序
        return sign(mul(convex_hull,a,b))>0||sign(mul(convex_hull,a,b))==0&&dis2(convex_hull,a)<dis2(convex_hull,b);
    }
    int convex(point *a,int n,point *b){ //计算含n个点的点集a的凸包b
        if(n<3) printf("Wrong in Line %d
    ",__LINE__); //顶点数小于3,输出失败信息
        for(int i=1;i<n;i++)                          //计算最低点convex_hull
            if(sign(a[i].x-a[0].x)<0||sign(a[i].x-a[0].x)==0&&sign(a[i].y-a[0].y)<0)
            swap(a[0],a[i]);
        convex_hull=a[0];
        sort(a,a+n,cmp);                      //按极角和距离排序
        int newn=2;
        b[0]=a[0];b[1]=a[1];                //a[0],a[1]入栈
        for(int i=2;i<n;i++){
            while(newn>1&&sign(mul(b[newn-1],b[newn-2],a[i]))>=0) --newn; //弹出栈顶所有未左转指向扫描顶点i的元素
            b[newn++]=a[i];                   //顶点i入栈
        }
        return newn;           //栈顶指针
    }
    int main(){
        scanf("%d%d",&n,&l);
        for(int i=0;i<n;i++)
            scanf("%lf%lf",&p[i].x,&p[i].y);
        n=convex(p,n,p);
        p[n]=p[0]; //首尾相连
        double ans=0;
        for(int i=0;i<n;i++)
            ans+=dis(p[i],p[i+1]);  //累计凸包边长
        ans+=2*pi*l;
        printf("%.0f
    ",ans);
        return 0;
    }
  • 相关阅读:
    webpack基础
    LeetCode232. 用栈实现队列做题笔记
    mysql 时间加减一个月
    leetcode 1381. 设计一个支持增量操作的栈 思路与算法
    LeetCode 141. 环形链表 做题笔记
    leetcode 707. 设计链表 做题笔记
    leetcode 876. 链表的中间结点 做题笔记
    leetcode 143. 重排链表 做题笔记
    leetcode 1365. 有多少小于当前数字的数字 做题笔记
    LeetCode1360. 日期之间隔几天 做题笔记
  • 原文地址:https://www.cnblogs.com/dashuzhilin/p/4541359.html
Copyright © 2011-2022 走看看