《Introduction to Algorithm》-chaper33-计算几何学
叉积:
在平面中我们为了度量一条直线的倾斜状态,为引入倾斜角这个概念。而通过在直角坐标系中建立tan α = k,我们实现了将几何关系和代数关系的衔接,这其实也是用计算机解决几何问题的一个核心,计算机做的是数值运算,因此你需要做的就是把几何关系用代数关系表达出来。而在空间中,为了表示一个平面相对空间直角坐标系的倾斜程度,我们利用一个垂直该平面的法向量来度量(因为这转化成了描述直线倾斜程度的问题)。
定义:

而向量的运算符合如下的代数定律.

显然这个定义式我们不怎么喜欢,因为它代数化程度还是太浅,主要就是由于角的正弦值我们不好找,但是这丝毫不影响这个定义式在应用当中的重要性,下面我们需要解决的问题就是,找到一个等价的代数化程度更高的定义式。
叉积的行列式公式:

①式子是叉乘得到的法向量的模长,由于在右手法则中的规定θ≤π,所以①两边一定是大于等于零的。但是现在我们做一些了不起的事情,通过基本定义和我们通过右手定则判定法向量的方向,将θ的范围限定在sinθ∈[0,1]的范围内,加入我们规定法向量的方向只有一个,我们就可以将向量的位置关系转移到模长的代数关系当中去。

而我们在计算几何学当中,往往不再去考察法向量,仅仅在二维平面中利用叉乘系数的代数关系,我们可以得到下面非常重要的结论:

判断线段相交:
通过上文叉积的引入,我们就可以利用它的性质涉及各种各样的算法,其中判断线段相交就是其中一个。
为了用到叉积的优良性质,这里需要从“跨立”的角度去理解线段相交。即一般情形下,两条线段相交,一条线段(segment_1)的两个端点是横跨在另一条线段(segment_2)所在直线的两侧的,同样也要满足另一条线段(segment_2)的两个端点横跨在前面线段(segment_1)所在直线的两侧。
而描述“横跨”这个几何位置的概念,就可以叉积了。
而对于一些比较特殊的情况,比如某一条线段上的点落在另外一条线段所在直线,需要特判一下,我们能够得到下述的伪代码形式:
SEGMENTS-INTERSECT(p1 , p2 , p3 , p4)//判断线段p1p2,p3p4是否相交.
d1 = DIRECTION(p3 , p4 , p1) ;
d2 = DIRECTION(p3 , p4 , p2) ;
d3 = DIRECTION(p1 , p2 , p3) ;
d4 = DIRECTION(p1 , p2 , p4) ;
if((d1 > 0 and d2 < 0 or d1 < 0 and d2>0) and ((d3 > 0 and d4 < 0 or d4 < 0 and d3>0))) return true;
else if(d1 = 0) and ON-SEGMENT(p3 , p4 , p1)
return true;
else if(d2 = 0) and ON-SEGMENT(p3 , p4 , p2)
return true;
else if(d3 = 0) and ON-SEGMENT(p1 , p2 , p3)
return true;
else if(d4 = 0) and ON-SEGMENT(p1 , p2 , p4)
return true;
else
return false;
DIRECTION(pi , pj , pk)//向量pkpi叉乘向量pjpi.
return (pk - pi)×(pj - pi).
ON-SEGMENT(pi , pj , pk)//判断点pk是否在线段pipj上.
if(min(xi , xj)≤xk≤max(xi , xj) and min(yi , yj)≤yk≤max(yi , yj))
return true
else
return false;
下面给出了几种线段相交的情形,以便于理解整个算法流程。

寻找凸包:
求一个点集V的凸包是计算几何中常见而且基本的算法,基于凸包寻找最近点对也将为时间复杂度上带来优化。
寻找凸包的算法整体上有Graham扫描法(Graham’s scan)以及Jarvis步进法(Jarvis march),他们都利用的叉积的性质,使用了一种称为“旋转扫除”的技术。
而构造凸包还有下面几个其他方法:
- 增量法:首先从左到右进行排序,得到点集V={v1 , v2 , …,vn}.然后构造凸包P(3)={v1,v2,v3},然后依次向后扫描,每次添加第i个点,并更新P(i-1),得到一个新的凸包P(i),扫描到点集中第n个点的时候,便完成了凸包的构造。
- 分治法:将点集一分为二,然后对子集进行递归的凸包运算
- 剪枝-搜索方法:在构造过程中,类似第九章的最坏情况下限行时间算法,它会进行两遍构造,分别完成凸包上链和下链的构造。
上面描述的方法非常的概括笼统,对于初学者来说会显得一头雾水,下面我们开始对逐个的分析算法步骤、正确性分析以及时间复杂度.
一般寻找构造凸包的算法,都是Graham扫描法/Jarvis步进法和下面的增量/剪枝-搜索/分治的方法结合起来,而不同的组合方法,往往依赖于不同的排序方式(水平序,极角序)。
基本Graham扫描法:
这种方法基于极角序,用一个栈S结构来储存凸包点集V1,然后更新到第i个点时,拿到当前栈顶的两个元素S[top] , S[top - 1],利用叉积考察这两个点和P[i]的相对位置(这就是前面我们所说的“旋转扫除”技术),更新凸包点集V1,下面呈现出这个算法的伪代码:
GRAHAM-SCAN(P)
let p0 be the point in P the minimum y-coordinate,
or the leftmost such point in case of a tie
let<p1 , p2 , ..., pn> be th remaining points in P ,
sorted by polar angle in counterclockwise order around p0
(if more tan one point has the same angle , remove all but
the on that is farthest from p0)
if m < 2
return "convex hull is empty"
else let S be an empty stack
PUSH(p0 , S)
PUSH(p1 , S)
PUSH(P2 , S)
for i = 3 to m
while the angle formed by points NEXT-TO-TOP(S) , TOP(S),pi
makes a nonleft turn
POP(S)
PUSH(pi , S)
return S
下面我们给出一个基本Graham扫描法的模拟过程:

寻找最近点对:
在交通控制等系统中,为检测出潜在的碰撞事故,在空中或者海洋交通系统中,需要识别两个距离最近的交通工具,抽象出来,最近点对就是给定点集P,找到相距最近的两个点。
朴素枚举的时间复杂度是O(n^2),这里我们介绍的分治算法能够将时间复杂度降到O(nlgn).
分治策略:
分解:找到一条垂直线L(在笛卡尔系中,x=a),它把点集P分为两个点集PL,PR.使得|PL| = |PR|并且PL、PR中所有的点都分布在垂线l的左侧和右侧。然后得到PL集合按照x、y坐标升序排列的辅助数组XL,YL,得到PR集合按照x、y坐标升序排列的辅助数组XR,YR.
对于每次递归进来,我们都需要按照x升序的数组P,因为只有这样我们才能确定垂直线L。这就是为什么分解问题的时候需要得到XL,XR,这是为了下面的递归过程准备按x升序排列的点集参数。而点集YL,YR有什么用处呢?在后面分析算法中另外一个辅助数组Y’我们就能够看到它们的用处。
解决:拿到PL,PR后,递归调用上面的以后我们已经构造好的寻找最近点对的算法,第一次调用的点集参数是PL,第二次调用的点集参数是PR.
合并:假设在上一步中,我们返回了两个值: δ1 , δ2分别代表分治后两个子问题的解集,δ = min(δ1 , δ2)和可能是当前问题的答案。为了确保答案正确,我们必须将那些没有遍历到的情况给考虑进来。能够看到,如果存在更优化的结果,则对应的两个点必然分布在以L为对称轴的δ * 2δ的矩形区域内,而容易看到,如果我们将P集合中分布在该区域的点放到按y坐标升序的Y ’中,则如果存在更优点对(pi,pj),那么j-i必然在[1,7],依据这条结论,我们将合并过程中的补充枚举过程的时间复杂度降低到O(n).
而为什么Y’中的更优点对的下标距离必然小于等于7呢?原理其实很简单,参考下面的图。

下面的问题是,我们如何构造Y’呢?我们基于进入递归调用中的点集X,得到的垂线L = a,为了构造Y’,我们基于点集P按y升序排列的集合Y,O(n)复杂度的情况下,通过判断横坐标是否在(a –δ,a+δ)范围内,便可以找到阴影区域中按照y排序的点集Y’.
总结起来,每次递归调用,我们需要点集X,Y,分治后需要找到对应子问题的点集参数XL,YL,XR,YR,而构造这些数组的时间复杂度都是O(n)的。
下面我们对这个算法进行时间复杂度的分析:
根据先前介绍过的主定理,T(n) = O(nlogn).
对于初始状态给出的无序的点集P,我们用O(nlogn)对其按x、y进行排序,之后的子问题就不再需要排序过程,利用O(n)的时间复杂度将X,Y数组折半即可得到XR,XL,YR,YL.
T’(n) = T(n) + O(nlogn)
对于初始状态给出的无序点集P,整个寻找最短点对的算法时间复杂度T’(n) = O(nlogn).
《Introduction to Algorithm》-chaper33-计算几何学的更多相关文章
- divide-conquer-combine(4.1 from the introduction to algorithm)
		this example is from chapter 4 in <the introduction to algorithm> the main idea is all showed ... 
- 《Introduction to Algorithm》-chaper30-多项式与快速傅里叶变换
		两个n次多项式的相加最直接的方法所需要的时间是O(n),而实现两个n次多项式的乘法的直接方法则需要O(n^2),本章讨论的快速傅里叶变换(FFT),将会将这一过程的时间复杂度降至O(nlogn).同时 ... 
- 《In Search of an Understandable Consensus Algorithm》翻译
		Abstract Raft是一种用于管理replicated log的consensus algorithm.它能和Paxos产生同样的结果,有着和Paxos同样的性能,但是结构却不同于Paxos:它 ... 
- Latex 算法Algorithm
		在计算机科学当中,论文当中经常需要排版算法.相信大家在读论文中也看见了很多排版精美的算法.本文就通过示例来简要介绍一下 algorithms 束的用法.该束主要提供了两个宏包,包含两种进行算法排版的环 ... 
- 广度优先搜索(BreadthFirstSearch)& 迪克斯特拉算法 (Dijkstra's algorithm)
		BFS可回答两类问题: 1.从节点A出发,有前往节点B的路径吗? 2.从节点A出发,前往节点B的哪条路径经过的节点最少? BFS中会用到"队列"的概念.队列是一种先进先出(FIFO ... 
- 【转载】VC维的来龙去脉
		本文转载自 火光摇曳 原文链接:VC维的来龙去脉 目录: 说说历史 Hoeffding不等式 Connection to Learning 学习可行的两个核心条件 Effective Number o ... 
- Google Interview University - 坚持完成这套学习手册,你就可以去 Google 面试了
		作者:Glowin链接:https://zhuanlan.zhihu.com/p/22881223来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 原文地址:Google ... 
- VC维的来龙去脉——转载
		VC维的来龙去脉——转载自“火光摇曳” 在研究VC维的过程中,发现一篇写的很不错的VC维的来龙去脉的文章,以此转载进行学习. 原文链接,有兴趣的可以参考原文进行研究学习 目录: 说说历史 Hoeffd ... 
- VC维的来龙去脉(转)
		本文转自VC维的来龙去脉 本文为直接复制原文内容,建议阅读原文,原文排版更清晰,且原网站有很多有意思的文章. 阅读总结: 文章几乎为台大林老师网课“机器学习可行性”部分串联总结,是一个很好的总结. H ... 
随机推荐
- 2014年辛星完全解读Javascript第一节
			***************概述*************** 1.Javascript是一种原型化继承的基于对象的动态类型的脚本语言,它区分大小写,主要运行在客户端,用户即使响应用户的操作并进行数 ... 
- 一个令人困惑的低效SQL
			整理之前的优化案例,觉得下面这个应该是开发很难发现也会很困惑的一个低效SQL. 看下面这个SQL.你看到这个SQL会不会感觉很正常.其实我刚看到也觉得正常得不得了.但是测试后它确实效率很低.selec ... 
- 角色控制器 Character Controller
			Unity中,1个单位尺寸代表1米.即在Unity中创建一个Cube的尺寸是1x1x1米大小. Unity推荐把人的身高定为大约2个Unity单位高度(2米). 为了截取角色的全身照,需要把角色Ins ... 
- 【web安全】第二弹:XSS攻防中的复合编码问题
			最近一直在研究XSS的攻防,特别是dom xss,问题慢慢的迁移到浏览器编码解码顺序上去. 今儿被人放鸽子,无奈在KFC看了两个小时的资料,突然有种豁然开朗的感觉. 参考资料先贴出来: 1. http ... 
- windows10 Build 10074版本上手体验(二)
- js数值计算
			js在小数数值计算时会出现误差,比如0.19+15.02=15.20999999999999,出现此问题的原因,百度上有,为了避免误差产生可以这样做:(0.19*100+15.02*100)/100. 
- vs2013运行c语言出现:无法查找或打开 PDB 文件。
			vs2013运行c语言出现:无法查找或打开 PDB 文件. “ConsoleApplication1.exe”(Win32): 已加载“C:\Users\hp\Documents\Visual ... 
- DIY RazorEngine 的程序集生成方式
			最近遇到一个项目,要使用RazorEngine做模板引擎,然后完成简易的CMS功能,以减轻重复的CDRU操作,同时复用管理后台.没错,使用的正是GIT HUB上的开源项目:https://github ... 
- [转载]常用Web Service汇总(天气预报、时刻表等)
			下面总结了一些常用的Web Service,是平时乱逛时收集的,希望对大家有用. ============================================ 天气预报Web Servic ... 
- Java集合ArrayList的应用
			/** * * @author Administrator * 功能:Java集合类ArrayList的使用 */ package com.test; import java.io.BufferedR ... 
