计算几何
半成品
误差分析
比如点的范围是 \(w\),那么斜率/极角误差要到 \(w^{-2}\)。
比如 \(w=10^9\),选取点 \((10^9,1)~(10^9-1,1)\),就可以估算范围是 \(\frac{1}{10^9-1}-\frac{1}{10^9}=\frac{1}{10^{18}}\)。
\(\operatorname{double}\) 最大 \(~2^{1024}\) 精度 \(10^{-15}\)
\(\operatorname{long double}\) 最大 \(~2^{2^{16}}\) 精度 \(10^{-18}\)
点积 Dot
判断角度,大于零为锐角,等于零为直角,小于零为钝角。
同时可以判断向量方向,正 OR 反。
求向量长度的时候,自己点积自己然后开方即可。
叉积 Cross
有向角 \(\theta\),注意点积有交换律,叉积没有。
\(P_1\times P_2>0\),\(P_2\) 在 \(P_1\) 逆时针方向。
\(P_1 \times P_2=0\),共线,此时可以再用点积判断同向还是异向。
\(P_1 \times P_2<0\),\(P_2\) 在 \(P_1\) 顺时针方向。
同时表示有向面积,逆时针面积为正。
极角排序
极角,\(\theta \in [-\pi,\pi)\)。
double 版本可以用函数 atan2(y,x)
,如果是 long double 版本就是 atan2l
但是精度和速度不太好。于是这里可以用 cmp 函数,用叉积判断逆时针和顺时针。先判断两点在上下半边的哪里,如果(y==0&&x<0)||y<0
就是在下办边,反之在上半边。如果在一边的话用叉积判断相对位置即可。
凸包
给出一些点,求可以包含这些点的最小多边形,即为凸包。
求法:\((x,y)\) 双关键字排序后先求下凸壳,再求上凸壳。用点积判断角度。严格凸包的话,等于要去掉。不严格的可以取等。
注意:如果有重点求不严格凸包会出问题,需要去重。
ICPC2023 济南M
题意:给你 \(n\) 个点,问小于等于 \(R+1\) 个点的简单多边形,包含所有点的有多少个。其中 \(R\) 为凸包大小,\(n \le 2000\),无三点共线。
解答:先求出凸包,然后一个暴力做法就是枚举每一个内部的点,再枚举每一条边和其他的点判断点是否在三角形内即可,复杂度 \(O(n^3)\)。
考虑优化,可以枚举点再统计
ZROI 2019省选十连测 第一场 T1
有 \(n\) 个点的图,点有点权 \(a_i\),也有点权 $b_i= \sum\limits_{j=1}^i a_j $。且 \(b_n=0\)。现在从 \(1\) 点开始遍历,经过任意点后回到点 \(1\)。从 \(i\) 点到 \(j\) 的收益式子为 \(\frac{a_i-a_i}{2 \times a_i \times a_j} \times b_i \times b_j\)。并且遍历时要求经过点的 \(b\) 权值,在到达某个村庄之前是单调不降的,而之后又是单调不增的。求最大收益,保留五位小数。
法一:排序枚举断点跑 spfa
法二:最长双调路径 dp
正解:我们发现收益式子很神秘,考虑拆开并且把相同下标地放一起,得到
这是一个向量叉乘的结果,考虑平面上的 \(n\) 个点\((B_i,\frac{B_i}{A_i})\),发现只需要维护一个凸包即可。
北京2018
经典问题
最近点对
KDT/分治/划格子
枚举 \(i \in[1,n]\),设 \(M\) 为目前最近点对的距离。
最小三角形
分治,先把点集按照中位数划分为两部分,然后分别求出两边的最小三角形。设目前最小的是 \(D\),于是沿着中间线向两边分别延长 \(\frac{D}{2}\),枚举每一个点再向下枚举 \(\frac{D}{2}\)。随机情况下 \(\frac{D}{2}\) 的矩形内点的个数为 \(O(1)\)。
ABC 234 Ex
划分格子
APIO2018
香港2022
题意:求区间最近点对。
KDT和分治显然不行。于是考虑划格子,第 \(i\) 份格子的边长为 \(2^{i+1}\),于是范围在 \([2^i,2^{i+1})\),
ucup2 Delft B
给定 \(n\) 个点,在边数为 \([3,k]\) 的路径,中最小化 \(\max(d(p_i,p_{i+1}))\),最小化的前提下求 \(k_{min}\),最后再求满足上述两个条件的路径个数。\(k \le30~n\le2\times 10^5\)
先求 \(k=3\) 的时候的答案,设为 \(M\)。
注意如果给的是点坐标而非点点近距离,要多从几何角度考虑。
ucup Delft H
给你 \(n\) 个点,有权值,要求找到一个矩形,满足内部点权值和-边长最大。矩形不要求与坐标轴平行。 n 400 8S
V图
概念:给 \(n\) 个点,求出对于每个点,以它为最近点的区域。
求法1:对于每个点求出它与其他点的中垂线,然后再半平面交。
求法2:随机切凸包
凸壳dp技巧
给 \(n\) 个点,求 \(5\) 个点的凸包的个数。
转化求一个环使得斜率递增。dp 状态枚举起点 \(s\),边 \((i,j)\) ,到的点个数,复杂度太大。可以对于 \(n^2\) 个点求向量,极角排序。枚举向量, \(dp(s,t)\) 表示从 \(s\) 出发只经过枚举过的向量到达 \(t\) 的方案数,对于边 \((u,v)\) ,有 \(dp(s,u) \to dp(s,v)\)
Best Sun
快速点定位
离线从左往右扫描线,维护一下各平面上下顺序。
在线,平衡树树 \(\to\) 可持久化平衡树,\(O(n\log n)\),难写。可以用树套树复杂度 \(O(n\log^2n)\),本质上求每个点最上面一条线是什么。
面积
求多边形面积
- 积分
- \(\frac{1}{2}\sum(P_i \times P_{i+1})\)
圆交面积
圆交
余弦定理
求解
弓形+多边形/格林公式(微积分)
辛普森积分
\(f(x)\) 表示图形与 \(x=t\) 交线的长度。所以面积为 \(\int f(x)dx\),不好直接积分。可以近似一下。如果 \(f(x)\) 为三次以下多项式就可以近似为 \(\frac{1}{6}(r-l)(f(l)+f(r)+4f(\frac{l+r}{2}))\)。
圆上经典问题
圆覆盖点
平面上有 \(n\) 个点,找一个圆覆盖其中 \(k\) 个点,问最小半径。
二分答案 \(R\),以每个点为圆心做一个半径为 \(R\) 的圆,查找是否有区域被覆盖了至少 \(k\) 次,区域查改为查圆弧交的次数。复杂度为 \(O(n^2\log n \log w)\),可以进一步优化。可以对于枚举每个圆单独二分,考虑第 \(i\) 个圆之前的答案,先看看这个圆能否满足,不过不满足就取判断下一个圆,如果满足就说明这个圆可能更新最小答案,那就对前 \(i\) 个圆整体的二分一次。先随机打乱圆,这样每个圆可能更新答案的概率是 \(\frac{1}{i}\),那么这一部分的期望复杂度就是 \(O(\sum\frac{1}{i}*i^2\log n\log w)\)。
PKUWC2018
求圆与一个简单多边形交的圆弧长度。
CF1446F Line Distance
经典二分答案,然后判断个数。然后需要以圆点为圆心画一个 \(R\) 的圆。如果在园内和圆上的点显然对其他所有点连线距离满足。园外两点连线需要与圆相切或相交,考虑最极限的情况,
CCPC Guangzhou 2021 L
考虑 \(k_i=1\),判断点是否在凸包内(求每一段直线,用叉积判断点是否在两段直线中间)。二分求切线即可。如果 \(k_i>1\),
闵可夫斯基和
给定两个凸包 \(A~B\),求凸包 \(C=A+B\)。
JSOI2018
居然一眼秒了。直接求 \(A-B\) 的闵可夫斯基和,判断向量是否在其中。
Yoko
混合饮料的过程就是缩小凸包的过程,于是直接求出原始饮料的闵可夫斯基和,以及目标饮料的闵可夫斯基和。判断是否包含。
CF1019E Raining season
简单多边形点包含
1.在内部/外部,作射线看有奇/偶个交点。
2.在边上,枚举边。