凸包--Graham扫描法
一直听大佬们说:凸包、凸包、凸包
一直不会。。。。。
然后。。。。
今天考试,考了一道计算几何的简单题。。。。
这,,,还是学一下吧。。
然后考试现场学习一下凸包算法。
先理解一下凸包是啥东西。
看看这张图
解释一下凸包是什么
如果你有一堆点(原谅我画的很凌乱)
那么,找到一个点集
依次连接这些点
使他们形成一个凸多边形
并且所有的点都包括在这个多边形的内部或者边上
这个多边形就是一个凸包(我写的肯定一点也不严谨)
不管怎么样,就先这样理解一下吧。。。。。。
凸包是啥应该不难理解,那么,给你一堆点,怎么求凸包?
这种东西。。。。。
先大概说一下把。。。
首先找到最靠近左下的那个点,这个点一定在凸包上(不难理解吧。。。画个图就知道了)
以这个点为极点,其他点按照极角排序
然后按照顺序依次访问所有点,判断可行性
这样子干说真是虚无缥缈的东西。。。。。。
画图来解释
这是一片点。
找到最靠近左下的一个点
其他的点按照极角排序
然后把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扫描法的更多相关文章
- [hdu contest 2019-07-29] Azshara's deep sea 计算几何 动态规划 区间dp 凸包 graham扫描法
今天hdu的比赛的第一题,凸包+区间dp. 给出n个点m个圆,n<400,m<100,要求找出凸包然后给凸包上的点连线,连线的两个点不能(在凸包上)相邻,连线不能与圆相交或相切,连线不能相 ...
- 【计算几何初步-凸包-Graham扫描法-极角序】【HDU1348】 WALL
Wall Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submi ...
- 凸包算法(Graham扫描法)详解
先说下基础知识,不然不好理解后面的东西 两向量的X乘p1(x1,y1),p2(x2,y2) p1Xp2如果小于零则说明 p1在p2的逆时针方向 如果大于零则说明 p1在p2的顺时针方向 struct ...
- 【BZOJ-1670】Building the Moat护城河的挖掘 Graham扫描法 + 凸包
1670: [Usaco2006 Oct]Building the Moat护城河的挖掘 Time Limit: 3 Sec Memory Limit: 64 MBSubmit: 464 Solv ...
- 计算几何 : 凸包学习笔记 --- Graham 扫描法
凸包 (只针对二维平面内的凸包) 一.定义 简单的说,在一个二维平面内有n个点的集合S,现在要你选择一个点集C,C中的点构成一个凸多边形G,使得S集合的所有点要么在G内,要么在G上,并且保证这个凸多边 ...
- Graham 扫描法找凸包(convexHull)
凸包定义 通俗的话来解释凸包:给定二维平面上的点集,凸包就是将最外层的点连接起来构成的凸多边型,它能包含点集中所有的点  Graham扫描法 由最底的一点 \(p_1\) 开始(如果有多个这样的点, ...
- 关于graham扫描法求凸包的小记
1.首先,凸包是啥: 若是在二维平面上,则一般的,给定二维平面上的点集,凸包就是将最外层的点连接起来构成的凸多边型,它能包含点集中所有的点. ───────────────────────────── ...
- Graham扫描法 --求凸包
前言: 首先,什么是凸包? 假设平面上有p0~p12共13个点,过某些点作一个多边形,使这个多边形能把所有点都“包”起来.当这个多边形是凸多边形的时候,我们就叫它“凸包”.如下图: 然后,什么是凸包 ...
- (模板)poj1113(graham扫描法求凸包)
题目链接:https://vjudge.net/problem/POJ-1113 题意:简化下题意即求凸包的周长+2×PI×r. 思路:用graham求凸包,模板是kuangbin的. AC code ...
随机推荐
- LeetCode - 627. Swap Salary
Given a table salary, such as the one below, that has m=male and f=female values. Swap all f and m v ...
- redis新手入门,摸不着头脑可以看看<二>
对<Redis开发与运维>的理解--下文中引号部分来自该书,略有修改 P19. Redis有序集合(图2-1) "Redis有序集合和集合一样也是某种类型元素的集合,不重复.不 ...
- [Python Study Notes]批量将wold转换为pdf
本文代码,由原ppt2pdf.py进行改写 '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ...
- 用mount挂载远程服务器网络硬盘
环境: 服务器:192.168.20.204 客户端:192.168.20.203 1. 在服务器配置/etc/export 添加可以共享的文件夹和允许的客户端地址 /home/dir 192.16 ...
- 置换群、Burnside引理与等价类计数问题
置换群.Burnside引理与等价类计数问题 标签: 置换群 Burnside引理 置换 说说我对置换的理解,其实就是把一个排列变成另外一个排列.简单来说就是一一映射.而置换群就是置换的集合. 比如\ ...
- sphinx初识
sphinx(SQL Phrase Index),查询词组索引. 定义:Sphinx是一个全文检索引擎. 特性: 1.高速索引 (在新款CPU上,近10 MB/秒); 2.高速搜索 (2-4G的文本量 ...
- php的内置函数debug_backtrace()与get_included_files()跟踪代码调用(Thinkphp框架举例)
debug_backtrace() 在我们开发一个项目中,或者二开研究某个开源程序,需要对代码流程一步步去跟踪,来研究它的逻辑,才可以进行修改,达到我们的开发目的.php的内置函数debug_back ...
- Jenkins系列——使用checkstyle进行代码规范检查
1.目标 通过jenkins使用checkstyle对代码进行规范检查并生成html报告. 构建采用shell. 2.环境 checkstyle5.7(如果是Linux版本选用tar.gz格式) ap ...
- Activity的生命周期& 启动模式
1.Activity的生命周期 生命周期这个事情,是android工程师最基础的知识,所以今天要讲的是一些不一样的东西. 1.1 OnStart,OnResume,OnPause,OnStop 他们的 ...
- 约瑟夫环-循环队列算法(曾微软,google笔试题)
这也是我们聚会时常常做的游戏之一. 算法思路: 此处我使用循环链表模拟人围城一圈,每一个结点代表一个人.链表是一个有序链表,链表结点数据域是一个整型,代表人的序号.出局等同于链表删除元素,每次出局后重 ...