一直听大佬们说:凸包、凸包、凸包

一直不会。。。。。

然后。。。。

今天考试,考了一道计算几何的简单题。。。。

这,,,还是学一下吧。。

然后考试现场学习一下凸包算法。

先理解一下凸包是啥东西。

看看这张图

解释一下凸包是什么

如果你有一堆点(原谅我画的很凌乱)

那么,找到一个点集

依次连接这些点

使他们形成一个凸多边形

并且所有的点都包括在这个多边形的内部或者边上

这个多边形就是一个凸包(我写的肯定一点也不严谨)

不管怎么样,就先这样理解一下吧。。。。。。


凸包是啥应该不难理解,那么,给你一堆点,怎么求凸包?

这种东西。。。。。

先大概说一下把。。。

首先找到最靠近左下的那个点,这个点一定在凸包上(不难理解吧。。。画个图就知道了)

以这个点为极点,其他点按照极角排序

然后按照顺序依次访问所有点,判断可行性

这样子干说真是虚无缥缈的东西。。。。。。

画图来解释

这是一片点。

找到最靠近左下的一个点

其他的点按照极角排序

然后把1丢到凸包的栈里面,准备开始扫描

检查2号点是否在1的一侧,(检查一下是不是凸多边形)

这里检查到2号可行,先加入到栈中

检查到3更加靠近外侧(如果加入3号就会形成凹多边形,显然3在凸包中,而2不在)

然后把2号点弹出栈,判断1号和3号节点的关系(同判断2号)

依次这么判断,最后所有凸包上的点都会在栈中


这样子算法的步骤很显然了。

继续解决一些细节上的问题(貌似就一个把。。。。)

怎么计算一个节点是否在前一个点的一侧。。。。

(我说的好不专业。。。我自己都不知道该怎么说一些名词。。。就将就着理解一下吧。。。)

我们先拿几个点出来

其中1,2,3是当前在凸包的栈中的点,4号节点是需要判断的点

那么,我们需要从栈中拿最上方的两个点(2和3节点)

把他们连接起来,再把2和4连接起来(怎么连接?我是不会说直接用向量的坐标表示就可以了)

计算一下两个向量的叉积。。

哈,叉积。。。

解释一下吧。。

假设2到3的向量是a(x1,y1)

2到4的向量是b(x2,y2)

那么,计算一下它们的叉积,也就是x1y2-x2y1

换种方法来表示就是。

|a|·|b|·sin<a,b>

(所以说叉积也可以用来求出三角形的面积~这个以后还会用到的)

如果,这两个向量的叉积≥0 证明这两个向量平行或者夹角是个锐角

也就证明了3号节点此时一定不再凸包上(因为连接2和4之后3在凸包内侧了)

把3号节点弹出栈,继续重复上面的步骤即可。


感觉我说的有点小复杂诶。。。。

这个东东多画点图就会理解的

如果还是不太清楚,可以看一看代码。

struct Node
{
int x,y;
}p[MAX],S[MAX];//p储存节点的位置,S是凸包的栈
inline bool cmp(Node a,Node b)//比较函数,对点的极角进行排序
{
double A=atan2((a.y-p[1].y),(a.x-p[1].x));
double B=atan2((b.y-p[1].y),(b.x-p[1].x));
if(A!=B)return A<B;
else return a.x<b.x; //这里注意一下,如果极角相同,优先放x坐标更小的点
}
long long Cross(Node a,Node b,Node c)//计算叉积
{
return 1LL*(b.x-a.x)*(c.y-a.y)-1LL*(b.y-a.y)*(c.x-a.x);
}
void Get()//求出凸包
{
p[0]=(Node){INF,INF};int k;
for(int i=1;i<=n;++i)//找到最靠近左下的点
if(p[0].y>p[i].y||(p[0].y==p[i].y&&p[i].x<p[0].x))
{p[0]=p[i];k=i;}
swap(p[k],p[1]);
sort(&p[2],&p[n+1],cmp);//对于剩余点按照极角进行排序
S[0]=p[1],S[1]=p[2];top=1;//提前在栈中放入节点
for(int i=3;i<=n;)//枚举其他节点
{
if(top&&Cross(S[top-1],p[i],S[top])>=0)
top--;//如果当前栈顶不是凸包上的节点则弹出
else S[++top]=p[i++];//加入凸包的栈中
}
//底下这个玩意用来输出凸包上点的坐标
//for(int i=0;i<=top;++i)
// printf("(%d,%d)\n",S[i].x,S[i].y);
}

接下来找一道简单点的例题

HDU 1392

这道题目就是求出凸包然后计算周长,很简单的题目,去试试吧。。

凸包--Graham扫描法的更多相关文章

  1. [hdu contest 2019-07-29] Azshara's deep sea 计算几何 动态规划 区间dp 凸包 graham扫描法

    今天hdu的比赛的第一题,凸包+区间dp. 给出n个点m个圆,n<400,m<100,要求找出凸包然后给凸包上的点连线,连线的两个点不能(在凸包上)相邻,连线不能与圆相交或相切,连线不能相 ...

  2. 【计算几何初步-凸包-Graham扫描法-极角序】【HDU1348】 WALL

    Wall Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submi ...

  3. 凸包算法(Graham扫描法)详解

    先说下基础知识,不然不好理解后面的东西 两向量的X乘p1(x1,y1),p2(x2,y2) p1Xp2如果小于零则说明  p1在p2的逆时针方向 如果大于零则说明 p1在p2的顺时针方向 struct ...

  4. 【BZOJ-1670】Building the Moat护城河的挖掘 Graham扫描法 + 凸包

    1670: [Usaco2006 Oct]Building the Moat护城河的挖掘 Time Limit: 3 Sec  Memory Limit: 64 MBSubmit: 464  Solv ...

  5. 计算几何 : 凸包学习笔记 --- Graham 扫描法

    凸包 (只针对二维平面内的凸包) 一.定义 简单的说,在一个二维平面内有n个点的集合S,现在要你选择一个点集C,C中的点构成一个凸多边形G,使得S集合的所有点要么在G内,要么在G上,并且保证这个凸多边 ...

  6. Graham 扫描法找凸包(convexHull)

    凸包定义 通俗的话来解释凸包:给定二维平面上的点集,凸包就是将最外层的点连接起来构成的凸多边型,它能包含点集中所有的点  Graham扫描法 由最底的一点 \(p_1\) 开始(如果有多个这样的点, ...

  7. 关于graham扫描法求凸包的小记

    1.首先,凸包是啥: 若是在二维平面上,则一般的,给定二维平面上的点集,凸包就是将最外层的点连接起来构成的凸多边型,它能包含点集中所有的点. ───────────────────────────── ...

  8. Graham扫描法 --求凸包

    前言: 首先,什么是凸包? 假设平面上有p0~p12共13个点,过某些点作一个多边形,使这个多边形能把所有点都“包”起来.当这个多边形是凸多边形的时候,我们就叫它“凸包”.如下图:  然后,什么是凸包 ...

  9. (模板)poj1113(graham扫描法求凸包)

    题目链接:https://vjudge.net/problem/POJ-1113 题意:简化下题意即求凸包的周长+2×PI×r. 思路:用graham求凸包,模板是kuangbin的. AC code ...

随机推荐

  1. Alex: 2018年对混合现实MR的展望

    原文作者:Alex Kipman, 微软操作系统工程院技术院士 Hello 大家好! 难以置信我们已经走过了2018年的头两个月了. 每年一月份我都会去巴西省亲,和我的家人欢聚一堂,度过一个美好的假日 ...

  2. Java中从控制台输入数据的几种常用方法(转)

    一.使用标准输入串System.in  //System.in.read()一次只读入一个字节数据,而我们通常要取得一个字符串或一组数字  //System.in.read()返回一个整数  //必须 ...

  3. maven排除jar包冲突

    首先查看mvn中冲突的包 使用命令:mvn dependency:tree -Dverbose | grep "omitted for conflict with" windows ...

  4. 分布式高性能消息处理中心HPMessageCenter

    # HPMessageCenter 高性能消息分发中心.用户只需写好restful接口,在portal里面配置消息的处理地址,消息消费者就会自动访问相关接口,完成消息任务. ### 部署说明 **创建 ...

  5. puppeteer,新款headless chrome!

    puppeteer puppeteer是一种谷歌开发的Headless Chrome,因为puppeteer的出现,业内许多自动化测试库停止维护,比如PhantomJS,Selenium IDE fo ...

  6. Nexus3将本地jar包添加到仓库

    新建一个文件夹,将要上传的jar包放进去,然后创建一个pom文件,例如xx.jar,pom.xml 首先创建一个目录 方便执行上传的时候url参数 也可以不创建, 上传XML curl -v -u a ...

  7. Java遍历文件目录

    函数介绍 File[] listFiles():返回当前文件的子目录或子文件的文件数组. 遍历目录 调用listFiles()即可得文件的子目录和子文件,如果存在子目录,那么子目录需要再次调用list ...

  8. CodeForces - 788B Weird journey 欧拉路

    题意:给定n个点,m条边,问能否找到多少条符合条件的路径.需要满足的条件:1.经过m-2条边两次,剩下两条边1次  2.任何两条路的终点和起点不能相同. 欧拉路的条件:存在两个或者0个奇度顶点. 思路 ...

  9. HDU - 1846 Brave Game 巴什博弈

    思路:直接判断n是不是m+1的倍数,若是先手则输,否则赢. AC代码 #include <cstdio> #include <cmath> #include <algor ...

  10. Android学习开发中如何保持API的兼容

    Android学习开发中如何保持API的兼容: 1,采用良好的设计思路 在设计过程中,如果能按照下面的方式来进行设计,会让这个API生命更长久 面向用例的设计,收集用户建议,把自己模拟成用户,保证AP ...