所谓凸包,就是一个凸出来的包

(逃)

前言

解析集合的第一课。
关键特征:周长最小。此时一定是凸包。

解析

定义

凸包:在平面上能包含所有给定点的最小凸多边形叫做凸包。

性质:凸包的周长是所有能包含给定点的多边形中最小的。

维护

凸包的主流求法有 Andrew 和 Graham,两者的复杂度瓶颈都在于排序,为 O(nlog⁡n)O(n\log n)O(nlogn)。
这里介绍较为简单的 Graham 扫描法。

首先,找出所有点中按照 X−YX-YX−Y 排序最小的点 OOO。
然后以 OOO 作为原点,把所有其它点按照极角排序,极角相同时按距离升序排序(实测这里也可以降序,但是绝对不能无序)。
可以用快排重载 cmp 函数的方法实现,利用叉积判断。

bool cmp(V a,V b){double d=(a-p[1])^(b-p[1]);if(abs(d)>eps) return d>0;else return len(a-p[1])<len(b-p[1]);
}

排好序后,开一个栈维护当前凸包中的点。
如果新点破坏了凸性,则不断退栈。
最终栈内的元素就是凸包中的点。

是否破坏凸性可以用叉积判断,如果新点和栈顶形成的向量向右拐了(叉积小于0),则说明破坏了凸性。

注意:这里判断退栈的条件最好带等!,一方面,共线时在边上的顶点没有什么意义,另一方面,当有重合点时,不带等会导致程序错误。

void ConvexHull(V *p,int &n){int top=0;sort(p+1,p+1+n);sort(p+2,p+1+n,cmp);top=0;for(int i=1;i<=n;i++){while((top>1&&((zhan[top]-zhan[top-1])^(p[i]-zhan[top]))<=0)) --top;zhan[++top]=p[i];}memcpy(p,zhan,sizeof(zhan));n=top;return;
}

完整代码

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

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f;
}//basic declare
//#define double long double
const double eps=1e-10;
const double pi=acos(-1.0);//---about vectors (or points)//definition
struct V{double x,y;V():x(0),y(0){}V(double a,double b):x(a),y(b){}
};
V ans[10];//declared for other functions
int tot;
inline void input(V &a){scanf("%lf%lf",&a.x,&a.y);}
void print(const V &a,int op=1){printf("%.10lf %.10lf",a.x,a.y);putchar(op?10:32);}
//op:endl or space//basic operation
inline V operator + (const V &a,const V &b){return (V){a.x+b.x,a.y+b.y};}
inline V operator - (const V &a,const V &b){return (V){a.x-b.x,a.y-b.y};}
inline V operator * (const double &x,const V &a){return (V){a.x*x,a.y*x};}
inline V operator * (const V &a,const double &x){return (V){a.x*x,a.y*x};}
inline V operator / (const V &a,const double x){return (V){a.x/x,a.y/x};}
inline bool operator == (const V &a,const V &b){return abs(a.x-b.x)<eps&&abs(a.y-b.y)<eps;}
inline bool operator != (const V &a,const V &b){return !(a==b);}
inline double operator * (const V &a,const V &b){return a.x*b.x+a.y*b.y;}
inline double operator ^ (const V &a,const V &b){return a.x*b.y-a.y*b.x;}
inline double len(const V &a){return sqrt(a.x*a.x+a.y*a.y);}
inline V mid(const V &a,const V &b){return (V){(a.x+b.x)/2,(a.y+b.y)/2};}
inline V chui(const V &a){return (V){a.y,-a.x};}//not take direction into account
inline V danwei(const V &a){return a/len(a);}
inline double tri_S(const V &a,const V &b,const V &c){return abs((b-a)^(c-a))/2;}//always be non-negative
inline bool operator < (const V &a,const V &b){return a.x<b.x-eps||(abs(a.x-b.x)<eps&&a.y<b.y-eps);
}
inline double ang(const V &a,const V &b){return acos((a*b)/len(a)/len(b));}
inline V rotate(const V &o,double t){//COUNTER_CLOCKWISEdouble s=sin(t),c=cos(t);return (V){o.x*c-o.y*s,o.x*s+o.y*c};
}const int N=1e5+100;
const int M=505;
int n,m;
V p[N],zhan[N];
bool cmp(V a,V b){double d=(a-p[1])^(b-p[1]);if(abs(d)>eps) return d>0;else return len(a-p[1])<len(b-p[1]);
}
void ConvexHull(V *p,int &n){int top=0;sort(p+1,p+1+n);sort(p+2,p+1+n,cmp);top=0;for(int i=1;i<=n;i++){while((top>1&&((zhan[top]-zhan[top-1])^(p[i]-zhan[top]))<eps)) --top;zhan[++top]=p[i];}memcpy(p,zhan,sizeof(zhan));n=top;return;
}
signed main(){#ifndef ONLINE_JUDGE//freopen("a.in","r",stdin);//freopen("a.out","w",stdout);
#endifn=read();for(int i=1;i<=n;i++) input(p[i]);ConvexHull(p,n);zhan[n+1]=p[1];double res(0);for(int i=1;i<=n;i++) res+=len(zhan[i+1]-zhan[i]);//print(zhan[i]);printf("%.2lf\n",res);return 0;
}
/*
3 5
0 -2
-5 3
0 -7
*/

模板:二维凸包(计算几何)相关推荐

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

    P2742 [USACO5.1]圈奶牛Fencing the Cows /[模板]二维凸包 题目: 给定一些点,问围住所有点所用的围栏的长度 题解: 凸包模板题 凸包详细 代码: #include&l ...

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

    题解: 二维凸包裸题 按照x坐标为第一关键字,y坐标为第二关键字排序 然后相邻判断叉积用单调队列搞过去 正反都做一次就好了 代码: #include <bits/stdc++.h> usi ...

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

    传送门 二维凸包的板子,抄yyb大佬的 //minamoto #include<bits/stdc++.h> #define rint register int #define inf 0 ...

  4. POJ4449(三维凸包+空间坐标旋转+二维凸包)

    题目:Building Design 题意: 题目就是给了一个凸多面题. 要把这个凸多面体放到地上,一个面要接触到地面. 求一种放法,使得最高点最高,最高点相同时使投影面积最小.输出最高点高度H和投影 ...

  5. POJ 3348 Cows(二维凸包)

    题目链接:https://cn.vjudge.net/problem/POJ-3348 题意:有一些数,坐标已知,要用这些树作为篱笆的顶点圈一块多边形的地养牛,每头牛占地大小50,问最多能养多少头牛. ...

  6. 金蝶K3Cloud 5.0 套打设计模板 二维码

    金蝶K3Cloud 5.0 套打设计模板 二维码 找了很久没找到,做个记录 条形码-属性-设置-编码: 另外K3这里的控件不能旋转,唉

  7. 二维凸包(模板) hdu 1348 求凸包的周长

    题目来源:http://acm.hdu.edu.cn/showproblem.php?pid=1348 凸包模板: const int N =1010; const double PI = 3.141 ...

  8. [洛谷P2742]【模板】二维凸包([USACO5.1]圈奶牛Fencing the Cows)

    题目大意:求一个点集凸包边长 题解:求凸包,直接求 卡点:发现在较后面数位上有较小的误差,还以为是浮点数误差,最后发现是构造函数写成了$int$类型 C++ Code: #include <al ...

  9. 二维凸包 Graham's Scan

    凸包是啥?? 凸包就是: 给定二维平面上的点集,凸包就是将最外层的点连接起来构成的凸多边型,它能包含点集中所有的点. 外层的红线 就是凸包 一般题目会让你求利用最外层凸包的一些性质如下面这道题 来看一 ...

最新文章

  1. 如何使用graphpad做柱形图_自建房如何做防雷接地?使用什么材料?卫生间等电位如何连接?...
  2. 6月17 表单验证
  3. Python3 多线程问题:ModuleNotFoundError: No module named 'thread',原因及解决办法。
  4. 2019五月到六月反思复盘
  5. go语言和java比_去过大场面试后,java程序员有没有必要转学Go语言?
  6. log4net环境配置
  7. 手机厂商探路互联网:硬件高利润时代已成历史
  8. 开源开放 | 疾病科室、心血管系统疾病知识图谱发布,助力电子病历系统建设...
  9. static关键字作用总结
  10. ubb php论坛程序,论坛UBB代码 推荐
  11. 推荐个 Java 开源商城项目,这个是真的好!
  12. 联想计算机wifi卸载,怎么卸载联想笔记本电源管理软件
  13. 2021-6-26 激光的工业应用
  14. 10.2项目干系人管理+信息系统项目管理+野马合集
  15. 电源管理芯片之 Regulator用法 Regulator framework
  16. 这份整理的图解Java(全彩版)火了,完整PDF开放下载
  17. r语言做断轴_手把手教你用R语言做回归后的残差分析
  18. openGauss专家亮相华为全联接大会2022高校专场——中科大北邮
  19. Anaconda奇怪问题记录:WARNING conda.exceptions:print_unexpected_error_report(1251): KeyError(‘pkgs_dirs‘)
  20. 18在protel DXP中PCB图中给电路板绘制边框、安装孔的方法介绍成都电路板设计

热门文章

  1. 干货整理:处理不平衡数据的技巧总结!收好不谢
  2. 2018年,该转行AI工程师吗?
  3. JAVA类思维_面向对象思维 Java中的类和对象及其应用
  4. java符号%3e%3e是什么意思,终于找到了!有了它你就可以读懂字节码了!
  5. python 字符编码处理_浅析Python 字符编码与文件处理
  6. java抓取新闻_【图片】【抓取】Java获取各大网站新闻【java吧】_百度贴吧
  7. python实现人脸识别_python人脸识别代码实现丨内附代码
  8. 怎么让图片手机上排列_荣耀手机系列档次怎么排列?
  9. echarts 地图自定义图标_DMKB08:Echarts 分段设色
  10. 获取html滚动条位置,pc和移动端获取滚动条的位置