zoukankan      html  css  js  c++  java
  • 凸包学习笔记

    例题:P2742 [USACO5.1]圈奶牛Fencing the Cows /【模板】二维凸包

    https://www.luogu.com.cn/problem/P2742

    之前一直没有学习过计算几何的知识,也没有遇到相关的题。但是最近发现这类型的题多了起来,于是决定学习一下计算几何的知识。

    以这道模板题为例,我们可以以y坐标最小的点为原点,对所有点进行极角排序。

    我用的极角排序的方法是比较与原点连线的斜率大小。

    然后按斜率从小到大枚举,每次遇到一个点,判断他是否可以覆盖之前的点,如果可以就弹栈,然后将这个点加入栈。

    因为已经按斜率排过序,所以如果一个点不能将上一个点弹出栈,也就不能将再上一个点弹出栈。

    最后再将原点加入栈,统计答案即可。

    还有一种简单的方法,使用atan2函数,在另一篇博客会有介绍。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define db double
    #define N 200000
    using namespace std;
    int n,num,i,mnk;
    db ans,mnx,mny;
    struct node{
        db x,y;
    }f[N],data[N];
    db dis(node x,node y){
        return sqrt((x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y));
    }
    int check(node x1,node x2,node y1,node y2){
        if ((x2.x-x1.x)*(y2.y-y1.y)>(y2.x-y1.x)*(x2.y-x1.y))
            return 1;
        if ((x2.x-x1.x)*(y2.y-y1.y)==(y2.x-y1.x)*(x2.y-x1.y))
            return 0;
        return -1;
    }
    int cmp(node x,node y){
        int temp=check(f[n],x,f[n],y);
        if (temp==1||temp==0&&dis(x,f[n])<dis(y,f[n]))
            return 1;
        return 0;
    }
    void swap1(node &x,node &y){
        node k;
        k=x;
        x=y;
        y=k;
    }
    int main(){
        scanf("%d",&n);
        mny=mnx=1e9;
        for (i=1;i<=n;i++){
            scanf("%lf%lf",&f[i].x,&f[i].y);
            if (f[i].y<mny){
                mnk=i;
                mnx=f[i].x;
                mny=f[i].y;
            }
            if (f[i].y==mny&&f[i].x<mnx){
                mnk=i;
                mnx=f[i].x;
                mny=f[i].y;
            }
        }
        swap(f[n],f[mnk]);
        sort(f+1,f+n,cmp);
        num=1;
        data[1]=f[n];
        for (i=1;i<n;i++){
            while (num>1&&check(data[num-1],data[num],data[num],f[i])<=0)
                num--;
            num++;
            data[num]=f[i];
        }
        data[++num]=f[n];
        for (i=2;i<=num;i++)
            ans+=dis(data[i],data[i-1]);
        printf("%.2lf
    ",ans);
        return 0;
    }
  • 相关阅读:
    下雪诗
    华视身份证阅读器100UC HTTP模式二次开发
    C# Action 和 Func 区别
    网站部署——文件系统
    前端-JavaScript DOM和BOM
    IO多路复用
    python-协程
    python-线程
    python-进程
    计算机与操作系统简介
  • 原文地址:https://www.cnblogs.com/Mohogany/p/13727008.html
Copyright © 2011-2022 走看看