计算几何/凸包/安德鲁算法
先说一下凸包是啥
抽象解释:在一个实数向量空间V中,对于给定集合X,所有包含X的凸集的交集S被称为X的凸包。X的凸包可以用X内所有点(X1,…Xn)的凸组合来构造(来自百度百科);
简单理解:对于一个平面空间上的点集,其中的一些点总可以构成一个凸多边形,这个多边形(包括边界)包含了改点集内所有的点,这个凸多边形就是凸包。
如图:
在计算几何领域,有很多个求凸包的方法,这里主要讲比较容易掌握安德鲁算法(Andrew’s Algorithm)(因为我菜…)
算法基本思路
1.将给定的集合的点按X坐标升序排序,X相同则按Y升序排序;
2.创建凸包上部:
将排序后的点按从小到大顺序加入凸包A,若新加入的点使凸包A不再是凸多边形,则逆序删除之前加入的点,直到重新变成凸多边形;
3.创建凸包下部:
将排序后的点按从大到小顺序加入凸包B,若新加入的点使凸包B不再是凸多边形,则逆序删除之前加入的点,直到重新变成凸多边形;
(显然排序后的第一个点和最后一个点必定在凸包上)
注:
若a X b > 0,表示a在b的顺时针方向上
若a X b < 0,表示a在b的逆时针方向上
若a X b == 0,表示a与b共线,但不确定方向是否相同
下面用图解说明一下安德鲁算法:
第一步,将最开始的两个点加入凸包。
第二步,按照顺序选定点Si(不入凸包),若Si在凸包的倒数第二个点和倒数第一个点构成的向量的逆时针方向,就从凸包中删除倒数第一个点,循环此过程,直至Si在该向量顺时针方向,此时将Si入凸包。
点2在点0指向点1的向量的顺时针方向,点2入凸包;
点3在点1指向点2的向量的逆时针方向,点2从凸包中删除,此时点3在点0指向点1的向量的顺时针方向,入凸包;
点4在点1指向点3的向量的顺时针方向,点4入凸包;
点5在点3指向点4的向量的逆时针方向,点4从凸包中删除,此时点5在点1指向点3的向量的顺时针方向,入凸包;
点6在点3指向点5的向量的逆时针方向,点5从凸包中删除,此时点6还在点1指向点3的向量的逆时针方向,点3从凸包中删除,此时点6在点0指向点1的向量的顺时针方向,入凸包;
最后点7在点1到点6的向量的顺时针方向,点7入凸包
凸包上部构建完成
下部同理
最后两部分相连,即可得凸包。
代码&例题
破oj3348 Cows
题目大意:
给出一些树的坐标,一这些树为顶点可以围成一片牧场,牧场中每50个单位可以放一头牛,问最多可以放多少牛。
求最大牧场面积,就是求凸包面积。
代码
1 | #include<iostream> |