文章目录
https://linxi99.gitee.io/20190211/ACM计算几何篇/
1 前言
1.1 计算几何算法
ACM各种算法中计算几何算是比较实际的算法,在很多领域有着重要的用途
常用算法包括经典的凸包求解,离散化及扫描线算法、旋转卡壳、半平面交等
1.2 计算几何题目特点及要领
-
大部分不会很难,少部分题目思路很巧妙
-
做计算几何题目,模板很重要,模板必须高度可靠
-
要注意代码的组织,因为计算几何的题目很容易上两百行代码,里面大部分是模板。如果代码一片混乱,那么会严重影响做题正确率。
-
注意精度控制
-
能用整数的地方尽量用整数,要想到扩大数据的方法(扩大一倍,或扩大sqrt2)。因为整数不用考虑浮点误差,而且运算比浮点快
1.3 预备知识
见ACM几何基础篇
https://linxi99.gitee.io/20190211/ACM几何基础篇/
https://blog.csdn.net/linxilinxilinxi/article/details/81750327
计算几何将用到大量基础篇中的函数与知识
2 凸包
2.1 定义
2.1.1 凸多边形
过多边形的任意一边做一条直线,如果其他各个顶点都在这条直线的同侧,则把这个多边形叫做凸多边形
凸包求解算法的基础便是凸多边形的定义与性质
2.1.2 凸包
假设平面上n个点,过某些点作一个多边形,使这个多边形能把所有点都“包”起来。当这个多边形是凸多边形的时候,我们就叫它“凸包”
形象理解:皮筋包裹钉子群
2.2 颜料配色问题
2.2.1 问题描述
假设每种颜料都拥有 ( R , G , B ) (R,G,B) (R,G,B)三种属性,表示该种颜料红色,绿色,与蓝色的化学成分所占的比重
给你若干种已有的不限量的颜料,问是否能够勾兑出目标颜料 ( R 0 , G 0 , B 0 ) (R_0, G_0, B_0) (R0,G0,B0)
2.2.2 问题简化
若只考虑 ( R , G ) (R, G) (R,G)这两种颜色
给定 X = ( 10 % , 35 % ) , Y = ( 16 % , 20 % ) X = (10\%, 35\%), Y = (16\%, 20\%) X=(10%,35%),Y=(16%,20%)
问是否能够配制出 U = ( 12 % , 30 % ) U = (12\%, 30\%) U=(12%,30%)的燃料
V = ( 13 % , 22 % ) V = (13\%, 22\%) V=(13%,22%)这一种呢
如果再给你一种 Z = ( 7 % , 15 % ) Z = (7\%, 15\%) Z=(7%,15%)颜料呢
2.2.3 问题抽象
将每一种颜料映射为二维欧氏空间中的一个点,我们可以将已经给定的颜料与目的颜料在空间中标定出来
经过观察与思考,我们可以发现,一个颜料能够被勾兑出来当且仅当该颜料对应的点,位于以给定颜料所构成的凸包之中
2.2.4 数学抽象
Given a point set S = { p 1 , ⋯   , p n } ⊆ ε 2 S = \{p_1, \cdots, p_n\} \subseteq \varepsilon ^ 2 S={ p1,⋯,pn}⊆ε2
Let λ = < λ 1 , ⋯   , λ n > ∈ R n , λ 1 + λ 2 + ⋯ + λ n = 1 \lambda = <\lambda _ 1, \cdots, \lambda _ n> \in R ^ n, \lambda _ 1 + \lambda _ 2 + \cdots + \lambda _ n = 1 λ=<λ1,⋯,λn>∈Rn,λ1+λ2+⋯+λn=1 and m i n { λ 1 , ⋯   , λ n } ≥ 0 min\{\lambda _ 1, \cdots, \lambda _ n\} \ge 0 min{ λ1,⋯,λn}≥0
The point
p = [ p 1 , ⋯   , p n ] λ = λ 1 p 1 + ⋯ + λ n p n p = [p _ 1, \cdots, p _ n]\lambda = \lambda _ 1 p _ 1 + \cdots + \lambda _ n p _ n p=[p1,⋯,pn]λ=λ1p1+⋯+λnpn
is called a convex combination of S
2.2.4.1 Convex Combination And Affine Combination
凸组合:Convex Combination
两个点的Convex Combination会是这两个点所构成的线段
仿射组合:Affine Combination
而两个点的Affine Combination将会确定这两个点所对应的那条直线
2.2.4.2 区别与联系
也就是说Convex Combination 是 Affine Combination的一个子集
原因便是
m i n { λ 1 , ⋯   , λ n } ≥ 0 min\{\lambda _ 1, \cdots, \lambda _ n\} \ge 0 min{ λ1,⋯,λn}≥0
这个根据生活实际添加的条件
2.3 构造凸包的初步尝试
2.3.1 转化思想
大事化小,小事化了
2.3.2 极性 Extremity
称最终对点集所构成的凸包有贡献的点具有极性
称其为极点 Extreme Point
通过观察,所谓的这些极点,我们可以找到一条穿过它们的直线,使得点集中的所有点都落在直线的同一侧
2.3.3 基于极点的凸包构造算法
类比冒泡排序,我们可以逐个判断每一个给定的点是否位于任何三个点所构成的三角形的内部
这样我们可以逐个剔除所有的非极点,从而得到所有的极点,即凸包的解
很容易想到,该算法的时间复杂度 O ( n 4 ) O(n ^ 4) O(n4)
2.3.4 基于极边的凸包构造算法
2.3.4.1 极边
类比极点的定义相应的我们也可以定义极边(Extreme Edge),它们具有类似的性质
很容易可以发现凸包边界上的边若取逆时针走向,点集中所有的都位于极边的左侧(ToLeftTest)
2.3.4.2 尝试实现
枚举所有点所有边,判断其左右位置相对关系,如果所有点都落在该边的某一侧,则该边为极边,其端点为极点
易得,时间复杂度为 O ( n 3 ) O(n ^ 3) O(n3)
2.4 更进一步
2.4.1 减而治之
类比插入排序
我们可以考虑根据之前数据已经构成一个凸包,当新点来临之后,我们便可以考虑当前的点是否位于多边形内部 isPointInPolygon()
若位于内部或边界之上,我们便可以断定该点对凸包没有贡献
否则,将该点与凸包所构成的两条支撑线(Support-Lines)缝合到已有答案集合之中,并舍弃失去极性的点
2.4.2 转向形式
Pattern Of Turns
利用每个顶点相对于当前试图加入的点的不同的转向形式,获得支撑线以及不被丢弃的所有点
2.4.3 优点与劣势
该算法为在线算法,可以动态的添加点,从而改变凸包形式
但其复杂度虽然达到了 O ( n 2 ) O(n ^ 2) O(n2),但还是不尽如人意