凸包定义

通俗的话来解释凸包:给定二维平面上的点集,凸包就是将最外层的点连接起来构成的凸多边型,它能包含点集中所有的点

Graham扫描法

  1. 由最底的一点 \(p_1\) 开始(如果有多个这样的点,那么选择最左边的),计算它跟其他各点的连线和 x 轴正向的角度,按小至大将这些点排序,称它们的对应点为 \(p_{2},p_{3},...,p_{n}\)。这里的时间复杂度可达 \(O(n \log {n})\)

  2. 以下图为例,基点为H,根据夹角由小至大排序后依次为H,K,C,D,L,F,G,E,I,B,A,J。下面进行逆时针扫描。



3. 线段<H, K>一定在凸包上,接着加入C。假设线段<K, C>也在凸包上,因为就H,K,C三点而言,它们的凸包就是由此三点所组成。但是接下来加入D时会发现,线段<K, D>才会在凸包上,所以将线段<K, C>排除,C点不在是凸包上。

4. 即当加入一点时,必须考虑到前面的线段是否会出现在凸包上。从基点开始,凸包上每条相临的线段的旋转方向应该一致。如果发现新加的点使得新线段与上线段的旋转方向发生变化,则可判定上一点必然不在凸包上。实现时可用向量叉积进行判断,设新加入的点为 \(p_{n + 1}\),上一点为 \(p_n\),再上一点为 \(p_{n - 1}\)。顺时针扫描时,如果向量 \(<p_{n - 1}, p_n>\) 与 \(<p_n, p_{n + 1}>\) 的叉积为正,则将上一点删除。

5. \(\color{red}{删除过程需要回溯,将之前所有叉积符号相反的点都删除,然后将新点加入凸包。}\)

Graham扫描法主要用一个\(\color{red}{栈}\)来解决凸包问题,点集 Q 中每个点都会进栈一次,不符合条件的点会被弹出,算法终止时,栈中的点就是凸包的顶点(逆时针顺序在边界上)。该算法具体步骤为

由于选择第一个基点时, 选择的是 y 坐标最小且最靠左的点, 所以极角取值范围 [0, 180), 我们关心的是极角的相对大小, 而不用求角度具体大小(虽然可以通过 \(\cos(\theta)\) 在 [0, 180)递减性质 来求实际角度大小), 所以极角排序可以通过向量叉积来做. 如果 \(p_1 \times p_2\) 向量叉积为正, 则 \(p_2\) 在 \(p_1\) 逆时针放心, 那么 \(p_2\) 与 x 正方向夹角比 \(p_1\) 大

旋转方向

叉积

有向量 \(p1\) 和 \(p2\), 我们可以把叉积理解为由点 \((0,0)\), \(\vec p_1\), \(\vec p_2\) 和 \(\vec p_1+ \vec p_2\) 所构成的平行四边形有向面积.

二维平面点叉乘行列式:

\[\vec p_1 \times \vec p_2 = \begin{bmatrix}
\vec i & \vec j & \vec k \\
a_x & a_y & 0\\
b_x & b_y & 0\\
\end{bmatrix} = (a_xb_y-a_yb_x)\space \vec k\]

相对坐标原点,若 \(\vec p_1 \times \vec p_2\)值为正,\(\vec p_2\) 在 \(\vec p_1\) 逆时针方向,若值为负,\(\vec p_2\) 在 \(\vec p_1\) 顺时针方向。相对公共端点 \(\vec p_0\),叉积计算为

\[(\vec p_1 - \vec p_0) \times (\vec p_2 - \vec p_0) = (x_1 - x_0) \times (y_2 - y_0) - (x_2 - x_0) \times (y_1 - y_0)
\]

一个简单的确定满足 “右手定则” 向量叉积的方向的方法是这样的:若坐标系是满足右手定则的,当右手的四指从 \(\vec a\) 以不超过 180 度的转角转向 \(\vec b\) 时,竖起的大拇指指向是 \(\vec c\) 的方向.

代码实现

#include <iostream>
#include <vector>
#include <climits>
#include <algorithm>
#include <stack>
using namespace std; template <typename T>
struct Point {
T x;
T y;
Point(): x(0), y(0){};
Point(T x_, T y_): x(x_), y(y_){};
}; bool isLeftTurn(Point<int> &p0, Point<int> &p1, Point<int> &p2) {
return (p1.x - p0.x) * (p2.y - p0.y) >= (p1.y - p0.y) * (p2.x - p0.x);
} int main() {
vector<Point<int>> points;
points.emplace_back(1, 1);
points.emplace_back(8, 0);
points.emplace_back(16, 8);
points.emplace_back(2, 8);
points.emplace_back(4, 4);
points.emplace_back(0, 5);
points.emplace_back(12, 6);
points.emplace_back(8, 4);
points.emplace_back(6, 2); // output: (8,0) (16,8) (2,8) (0,5) (1,1)
if (points.empty()) {
return 0;
}
int y_min = INT_MAX;
int x_min = INT_MAX;
int start_index = 0;
for (int i = 0; i < points.size(); i++) {
if (points[i].y < y_min) {
y_min = points[i].y;
x_min = points[i].x;
start_index = i;
} else if (points[i].y == y_min) {
x_min = points[i].x;
start_index = i;
}
}
vector<Point<int>> st;
st.emplace_back(0, 0);
points.erase(points.begin()+start_index);
for (auto &point : points) {
point.x -= x_min;
point.y -= y_min;
} sort(points.begin(), points.end(), [](Point<int>& p1, Point<int>& p2) {
if (p1.x * p2.y == p1.y * p2.x) {
return p1.x * p1.x + p1.y * p1.y < p2.x * p2.x + p2.y * p2.y;
}
return p1.x * p2.y > p1.y * p2.x;
}); st.push_back(points[0]);
for (int i = 1; i < points.size();) {
if (isLeftTurn(st[st.size() - 2], st.back(), points[i])) {
st.push_back(points[i]);
i++;
} else {
st.pop_back();
}
} for (auto &i : st) {
cout << i.x + x_min << '\t' << i.y + y_min << endl;
}
return 0;
}



参考: https://blog.csdn.net/u012328159/article/details/50808360

Graham 扫描法找凸包(convexHull)的更多相关文章

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

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

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

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

  3. Graham扫描法 --求凸包

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

  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扫描法、andrew算法求凸包

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

  6. Graham扫描法

    Graham扫描法求凸包的模板 运行之后可以得到存有凸包顶点的栈s和栈顶指针top,n代表总点数 这个模板我当时调了很久,主要难点有两个,一个是正确的极角排序,一个是出栈入栈的细节操作,逆时针扫描,这 ...

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

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

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

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

  9. 凸包模板——Graham扫描法

    凸包模板--Graham扫描法 First 标签: 数学方法--计算几何 题目:洛谷P2742[模板]二维凸包/[USACO5.1]圈奶牛Fencing the Cows yyb的讲解:https:/ ...

随机推荐

  1. Scoring and Modeling—— Underwriting and Loan Approval Process

    https://www.fdic.gov/regulations/examinations/credit_card/ch8.html Types of Scoring FICO Scores    V ...

  2. u-boot(二)makefile

    目录 u-boot(二)makefile 引入 目录结构(1.1.6) 配置文件 目标 配置具体的单板 编译阶段 过程 链接入口 配置链接地址 附录 附录A:mkconfig解析 附录B 链接脚本 t ...

  3. Tensorflow object detection API 搭建物体识别模型(四)

    四.模型测试 1)下载文件 在已经阅读并且实践过前3篇文章的情况下,读者会有一些文件夹.因为每个读者的实际操作不同,则文件夹中的内容不同.为了保持本篇文章的独立性,制作了可以独立运行的文件夹目标检测. ...

  4. Map_占位符(嗨没想好怎么起名字)

    Map 是很好的集合,为我们带来了在其他语言(比如 Perl)中经常可见的好用的键/值对集合.JDK 以 HashMap 的形式为我们提供了方便的 Map 实现,它在内部使用哈希表实现了对键的对应值的 ...

  5. Hortonworks官网文档怎么找?

    Hortonworks官网文档怎么找? 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 俗话说,授人予鱼不如授人予渔,网上部署HDP的部署方式的博客有很多,看得你是眼花缭乱的.其实万 ...

  6. 【.net】“Newtonsoft.Json”已拥有为“Microsoft.CSharp”定义的依赖项。

    #事故现场: “Newtonsoft.Json”已拥有为“Microsoft.CSharp”定义的依赖项. #事故原因: 安装的Newtonsoft.Json版本为11.0.2,版本过高,与Micro ...

  7. Ext.net获取选中行数据

    两种方法 1.直接返回对象列表 <DirectEvents> <Click> <ExtraParams> <ext:Prameter Name="V ...

  8. 【八】Spring Cloud Config

    一.分布式系统面临的--配置问题 微服务意味着要将单体应用中的业务拆分成一个个子服务,每个服务的力度相对较小,因此系统中会出现大量的服务.由于每个服务都需要必要的配置信息才能运行,所以一套集中式的.动 ...

  9. bzoj 1531 Bank notes 多重背包/单调队列

    多重背包二进制优化终于写了一次,注意j的边界条件啊,疯狂RE(还是自己太菜了啊啊)最辣的辣鸡 #include<bits/stdc++.h> using namespace std; in ...

  10. mybatis-servlet.xml配置SpringMVC样板

    <?xml version="1.0" encoding="UTF-8" ?><beans xmlns:xsi="http://ww ...