凸包问题Finding the convex hull

问题描述:找到包含点集Q的最小凸多边形。使得点集内的点均在凸多边形的边上或内部。

即集合内任意两点的连线均在凸多边形内部。

输入:平面上的n个点的集合Q

输出: CH(Q):Qconvexhull

(一)蛮力法思路:

找到点集内的内部点去掉,剩余未边界点。

内部点的判断:只要其中三点A,B,C构成的三角形包含的点P则P为内部点。

三角形内部点具体判断方法:

如果P在△ABC内部,则A,P两个点在BC同侧;P,B两个点在AC同侧;C,P两个点在AB同侧。转换为点与线关系的判断。

判断点P与直线AB的关系的方法:

AB的直线方程g(x,y)=0.

P(x0,y0)与AB共线,则g(x0,y0) = 0;

P(x0,y0)在直线AB一侧,则g(x0,y0) > 0 或g(x0,y0)<0

所以判断两个点P(x0,y0),Q(x1,y10)是否在直线AB的同侧只需要判断:g(x0,y0)*g(x1,y1)>0是否成立。

时间复杂度分析:对于任意四个点A,B,C,D均需要判断,所以T(n)=θ(n^4)

优化方式:固定一个点(min y点),遍历其余三个点,也可以找到所有内部点

(二)Graham-Scan算法

基本思想

–当沿着Convex hull逆时针漫游时,总是向左转

–在极坐标系下按照极角大小排列,然后逆时针方向漫游点集,去除非Convex hull顶点(非左转点)。

关于向左旋转,一会在讨论,先给出基本算法框架

数据结构:使用栈

1.  找出点集Q中y-坐标值最小的点P-0

2.  按与P-0极角(逆时针方向)大小排序Q中其余点,结果记为<P1, P2, …, Pm>;

3. Push(p0, S); Push(p1, S); Push(p2, S);

4. FOR i=3 TO m DO

5.   While Next-to-top(S)、Top(S)和pi形成非左移动 Do

6.       Pop(S);

7.    Push(pi, S);

8. Rerurn S.

关于建立极坐标和排序以及初始化栈即Step1,2,3如下图:

(--图片来源ppt 课件)

关于判断左转,我的想法是转换为判断点和线的关系:

(--图片来源ppt 课件)

如图判断在当前状态下p2是否要保留,判断p2和p0是否在p1,p3的同侧即可。P2和P0在P1P3的同侧所以P2不符合条件,Pop(p2).

同理判断P3在当前状态下是否保留,判断P3是否与P0位于P1P4同侧,不同侧所以进行保留。

所以第4-7步需要线性时间即可。(每个点最多进栈出栈一次)

但是第二步基于比较的排序最快需要O(nlogn).

所以时间复杂度T(n)=O(nlogn)。

注意事项:

1.      最后节点p10不用判断

2.      关于左转可能有别的思路,我也只是有这样的思路

(三)分治算法

先来看整体算法框架:

Preprocess: (T(n)=O(1))

1.如果|Q|<3, 算法停止;

2.如果|Q|=3, 按照逆时针方向输出CH(Q)的顶点;

Divide:( T(n)=O(n))

选择一个垂直于x-轴的直线把Q划分为基本相等的两个集合QL和QR, QL在QR的左边;

Conquer: (T(n)=2T(n/2))

递归地为QL和QR构造CH(QL)和CH(QR);

Merge: T(n)=O(n)

1.找一个QL的内点p;

2.在CH(QR)中找与p的极角最大和最小顶点u和v;

3.构造如下三个点序列:

(1) 按逆时针方向排列的CH(QL)的所有顶点,

(2) 按逆时针方向排列的CH(QR)从u到v的顶点,

(3) 按顺时针方向排列的CH(QR)从u到v的顶点;

4.合并上述三个序列;

5.在合并的序列上应用Graham-Scan.

详细说明如图

(--图片来源ppt 课件)

注意此处虽然同样用了Graham-Scan.但是输入数据已经为排序的了,所以可以在线性时间内完成,而不是O(nlogn)。

总时间复杂度T(n)=2T(n/2)+O(n)= O(nlogn)

总结:

分治算法和Graham-Scan时间复杂度均为O(nlogn),而且事实上最佳状况也是O(nlogn),

具体证明主要是基于排序问题的最佳时间复杂度为O(nlogn)。

时间: 2024-11-06 09:40:02

凸包问题Finding the convex hull的相关文章

[算法课][分治]寻找凸包 (Convex Hull)

凸包问题是算法中经典的题目了,最近算法课讲分治问题时提到了Convex Hull,算法导论的书上也花了篇幅讨论了Convex Hull的求解,主要是Graham方法. 为了能更好地理解分治和Graham这两种解法,我决定自己动手把代码写一遍. 然而,在写之前,我发现我大一学的用行列式求解由三个点围城的三角形面积已经忘得差不多了,现在补充一下: 利用这个计算结果来判断点p3在p1p2直线的左侧还是右侧 下面是分治算法求解: #include <iostream> #include <alg

凸包(Convex Hull)构造算法——Graham扫描法

凸包(Convex Hull) 在图形学中,凸包是一个非常重要的概念.简明的说,在平面中给出N个点,找出一个由其中某些点作为顶点组成的凸多边形,恰好能围住所有的N个点. 这十分像是在一块木板上钉了N个钉子,然后用一根绷紧的橡皮筋它们都圈起来,这根橡皮筋的形状就是所谓的凸包. 计算凸包的一个著名算法是Graham Scan法,它的时间复杂度与所采用的排序算法时间复杂度相同,通常采用线性对数算法,因此为\( O\left(N\mathrm{log}\left(N\right)\right) \).

zoj 3871 Convex Hull(凸包)

题目链接:zoj 3871 Convex Hull 枚举每条边,计算出有多少情况下为凸包的边界,即有多少点在该边的左边. #include <cstdio> #include <cstring> #include <cmath> #include <vector> #include <complex> #include <algorithm> using namespace std; typedef pair<int,int&g

opencv笔记(二十四)——得到轮廓之后找到凸包convex hull

当我们得到一张轮廓之后,我们可以对其运用convexHull方法,寻找该轮廓的凸包. 一个轮廓可以有无数个包围它的外壳,而其中表面积最小的一个外壳,就是凸包. void convexHull(InputArray points, OutputArray hull, bool clockwise=false, bool returnPoints=true ) points是一个contour. vector<Point>类型或者Mat类型 hull是输出,也是一个点集vector<Poin

Computational Geometry PA1 Convex Hull (凸包)

题目链接:http://dsa.cs.tsinghua.edu.cn/oj/problem.shtml?id=710 CG2015 PA1-1 Convex Hull (凸包) Description (描述) After learning Chapter 1, you must have mastered the convex hull very well. Yes, convex hull is at the kernel of computational geometry and serv

Monotone Chain Convex Hull(单调链凸包)

1 Monotone Chain Convex Hull(单调链凸包)算法伪代码: 2 //输入:一个在平面上的点集P 3 //点集 P 按 先x后y 的递增排序 4 //m 表示共a[i=0...m]个点,ans为要求的点; 5 struct P 6 { 7 int x,y; 8 friend int operator < (P a, P b) 9 { 10 if((a.x<b.x) || (a.x==b.x && a.y<b.y)) 11 return 1; 12 r

OpenCV入门之寻找图像的凸包(convex hull)

介绍   凸包(Convex Hull)是一个计算几何(图形学)中的概念,它的严格的数学定义为:在一个向量空间V中,对于给定集合X,所有包含X的凸集的交集S被称为X的凸包.  在图像处理过程中,我们常常需要寻找图像中包围某个物体的凸包.凸包跟多边形逼近很像,只不过它是包围物体最外层的一个凸集,这个凸集是所有能包围这个物体的凸集的交集.如下图所示: 在上图中,绿色线条所包围的凸集即为白色图形的凸包.  在opencv中,通过函数convexHulll能很容易的得到一系列点的凸包,比如由点组成的轮廓

OpenCV Tutorials &mdash;&mdash; Convex Hull

凸包 找到物体的轮廓之后,再找其凸包   void convexHull(InputArray points, OutputArray hull, bool clockwise=false, bool returnPoints=true ) Parameters: points – Input 2D point set, stored in std::vector or Mat. hull – Output convex hull. It is either an integer vector

convex hull - Graham&#39;s scam Algorithm version-0.1

input:a finite set of two dimentional points P (the number of points n is more than 2) output: the convex hull of P Pesudo: 1, sort P in Lexgrahical order 2, construct the upper hull UHLL: 1' add two points on UHLL 2' for i=3 to  n add P[i] on UHLL W