[翻译]扫描线算法(Line Sweep Algorithm)(1)
原地址:https://www.hackerearth.com/zh/practice/math/geometry/line-sweep-technique/tutorial/
在cf评论区偶然看见的,顺便学习一下好了……然后发现是个大坑
我英语比较菜,如有谬误还请纠正……
在这篇文章,我们将会学到一些基于计算几何的算法。
扫描线是一条想象中的向右扫过平面的竖直线。也因此,以此思想为基础的算法也被称为平面扫描算法(Plane Sweep Algorithm),我们以某些事件为基础扫描我们思考的问题以使扫描离散化。
这些事件都是以我们思考的问题为基础,我们将在下面讨论的算法中看见。除去这些事件以外,我们需要维护一些数据结构来储存以y坐标为顺序排列的点(这一顺序有时可能会改变)以助益于在扫描到某些事件时进行操作。在一些情况,该数据结构只储存活动事件。
另一个需要注意的事情是,这种算法的效率取决于我们选用的数据结构。一般地,我们可以用C++中的set,但有时可能我们需要储存更多东西,所以我们可能采用平衡二叉树。
让我们思考我们的第一个算法。
最近的点(Closest Pair)
问题:从互不相同的N个点中找出最近的两个。
这个问题可以通过暴力枚举每两个点解决,不过这样复杂度为O(N2)O(N^2)。因此我们需要更好的算法,这里我们使用扫描线算法。
对这个问题我们可以考虑在数组中作为事件的的点。在一个set中,我们将已经访问过的点按y坐标排列,因此在从左向右扫描时首先我们以x坐标排序。
现在想象我们已经扫描过1至N-1,令h为我们得到的最短距离。对第N个点,我们想要找到距离小于等于h的点,而对于横坐标,只有横坐标范围在[xN−h,x][x_N-h,x]内,纵坐标范围在[xN−h,xN+h][x_N-h,x_N+h]内的才是我们需要担心的点。这些就是对于set的活动事件,在set中所有横坐标小于xN−hx_N-h的都会被删除。接下来我们再向set加入第N个点。
一个需要注意的事情是,对许多情况,是活动事件的点的数量是O(1)的(除该点本身外最多可以有5个点是活动的)(不是很懂这句,原句:One thing to note is that at any instance, the number of points which are active events is O(1)(there can be atmost 5 points around a point which are active excluding the point itself))
好的,理论已经够多了,让我们看看这个算法的运作。
将h初始化为开始的两个点,若现在的距离小于h则更新h的值。
图片中红色区域包括的点是被当前点评估的点。这些点左侧是已经被移除set的点。
下面是上述算法的cpp代码:
#define px second
#define py first
typedef pair<long long, long long> pairll;
pairll pnts [MAX];
int compare(pairll a, pairll b)
{ return a.px<b.px;
}
double closest_pair(pairll pnts[],int n)
{sort(pnts,pnts+n,compare);double best=INF;set<pairll> box;box.insert(pnts[0]);int left = 0;for (int i=1;i<n;++i){while (left<i && pnts[i].px-pnts[left].px > best)box.erase(pnts[left++]);for(typeof(box.begin()) it=box.lower_bound(make_pair(pnts[i].py-best, pnts[i].px-best));it!=box.end() && pnts[i].py+best>=it->py;it++)best = min(best, sqrt(pow(pnts[i].py - it->py, 2.0)+pow(pnts[i].px - it->px, 2.0)));box.insert(pnts[i]);}return best;
}
让我们来分解一下上述代码:
1.首先,我们以x为参数排序了点的数组
2.之后我们将数组pnts的第一个点加入了set中。注意,我们已经将纵坐标作为pair的第一个参数,所以set将以y坐标为参数排列。
3.在第一重循环的第一个子循环中,对每个pnts中的点,我们清除掉[XN−h,XN][X_N-h,X_N]以外的点,这一过程是O(N)的因为我们只有N个元素。由于删除的复杂度是O(logn),所以这一系列操作的复杂度是O(NlogN)
4.在第二个子循环中,我们遍历了所有所有横坐标在[xN−h,x][x_N-h,x]内,纵坐标范围在[xN−h,xN+h][x_N-h,x_N+h]内的点,找到lower_bound是logn的,而这一循环最多进行5次。
5.将每个点插入至set中,O(logn)
综上所述,时间复杂度为O(NlogN)。接下来让我们看下一个问题。
[翻译]扫描线算法(Line Sweep Algorithm)(1)相关推荐
- [翻译]扫描线算法(Line Sweep Algorithm)(2)
NOIPD110分滚粗. 心累. 学点有趣的治愈一下. 突然想起似乎之前还有个坑没有填,就练一波英语阅读. 矩形面积交 给出一个集合包含N个与坐标轴对称的矩形(矩形的边与x轴.y轴平行),找到所有的矩 ...
- 【CV系列】扫描线算法区域填充
DATE:2019-5-19 1.参考 算法系列之十二:多边形区域填充算法--扫描线种子填充算法 扫描线种子填充算法 扫描线算法完全解析 Line Sweep Technique [翻译]扫描线算法( ...
- 论文翻译--[TPAMI 2021]Deep Hough Transform For Semantic Line Detection
目录 深度霍夫变换语义直线检测 摘要 1,引言 2,相关工作 3,方法 3.1直线参数化和反转 3.2 深度霍夫变换的特征变换 3.3 在参数空间上进行直线检测 3.4 反转映射 3.5 边缘导向 ...
- 《Adapting the Tesseract Open Source OCR Engine for Multilingual OCR》论文翻译
本文是Tesseract在多语种方面OCR改进措施,刚好最近也在做相关工作,就顺便翻译了下.总的来说,看完之后对自己的相关工作也有一定的启发,感觉还不错,就在这分享一下.目前只翻译了下ocr的版面分析 ...
- 求解VRP问题的节约里程法、sweep扫描算法和λ互换法
第05章 求解容量约束车辆路径问题的启发式算法 Edited by Jiannywang@163.com 目 录 5.1 节约里程法. 1 5.1.1 C-W节约算法简介. 1 5.1.2 C-W ...
- 多边形快速凸包算法(Melkman‘s Algorithm)
前言 平面点集的凸包算法一文介绍了如何计算平面点集或者任意多边形的凸包.对于随机的平面点集,Graham scan和Andraw's 单调链算法已经是最快的算法了.但是对于没有自相交的封闭的简单多边形 ...
- Leetcode题目分类指南(单独刷题或学习算法书籍配合使用)
Leetcode题目分类指南 笔者在学习<算法导论>同时,希望能够配合Leetcode的题目进行分类模块化练习,该分类为笔者自己根据做题学习经验,结合<算法导论>的内容,给出L ...
- 计算机英语·总篇·A-Z
A Albel·Niels·Henrik,阿贝尔·尼尔斯·亨里克 albelian group,阿贝尔群 aborts,终止 absolute value and branch mispredicti ...
- 线段求交算法对比研究
线段求交算法对比研究 -----by wangsh 一.介绍 线段求交算法在计算几何,地理信息系统算法等相关应用中占有重要的位置,本文简单给出算法说明. Bentley & Ottmann于1 ...
最新文章
- LeetCode 968. 监控二叉树
- Response_功能介绍
- C# -WinForm 中英文实现, 国际化实现的简单方法
- [渝粤教育] 西南科技大学 畜牧概论 在线考试复习资料
- Linux下实现视频读取(二)---camera參数设定
- VC跨进程数据(结构体)传递-WM_COPYDATA
- 菜鸟的MySQL学习笔记(一)
- 强化学习的数学基础4---Q-Learning进阶
- oracle11g 时间失效,关于oracle11g RAC 的CTSS与ntp时间同步的疑问
- 2013年全国各大著名的IT公司薪资待遇大揭密 给出入职场的民工一点建议
- ARM64体系结构与编程之cache必修课(中)
- BabeLua常见问题
- 计算模型的GFLOPs和参数量 举例VGG16和DETR
- boder-radius属性
- 股市股票基金市场研报合集(2022年,共195份)
- python获取字典末端value值的取值方式
- 浅析原代细胞应用现状
- ubuntu简易教程(如何使用noi linux)
- 从简单的信道估计说起
- 北京自考计算机网络专科课程,北京08自考计算机网络(独本)课程设置