【学习笔记】计算几何
只写我会的。
封装好再用,注意精度。
这里定义角度
记一条直线
其实就是点,线段,直线,多边形,圆的组合。
因为本身自带大常数,一般来说理论复杂度能过就不会超时。
- 正弦定理:令
为三角形外接圆半径,则 , 为一条边, 为边 的对角。 - 余弦定理:令
为三角形三边, 为 的对角,则 。这给了我们角度与长度的换算。 。
极坐标系
类似平面直角坐标系,同样有原点
设
如果限制
与平面直角坐标系的转换
点
点 atan2(y,x)
是 STL 中自带的函数。
向量
既有大小又有方向的量称为向量。或者称作一个有向线段,即带有起点,长度,方向的线段。一般表示为
特殊的向量:
- 零向量:模长为
,记作 。方向任意。 - 单位向量:大小为
的向量为该方向的单位向量。
平行向量:方向相同或者相反的两个非零向量。记作
相等向量:模相等且方向相同的向量。相对地,相反向量指模相等但方向相反的向量。
向量计算:
加减:定义向量
数乘:定义向量
点乘:定义向量 acos
得到
叉乘:定义向量
移动向量:朝一个方向向量
有向量
叉乘没有交换律,但是
角度计算中,
旋转向量
对于向量
存储(表示)
存储一个点(向量):直接存储坐标。
存储一条直线:以直线上任意一点
判断问题:
两向量垂直:
两向量平行或相同:
折线段拐向:
对于点
记
点是否在线段上:
对于点
两线段是否相交:
对于线段
跨立实验可以解决很多线段直线之类的相交问题,这里不多写。
判断点是否在圆内
判断点到圆心的距离是否小于等于半径即可。
判断点是否在凸多边形内
可以做到
注意到凸多边形以最左下角为原点建立极坐标系,其边满足按极角大小排序。考虑求凸包的极角排序过程,可以直接二分找到夹住它的两个点,然后看拐向是否代表被凸包包含。
提前特判超过凸包边界的情况,即特别处理
注意到按顺序给出的多边形的预处理线性仅因为需要找到最左下角的点,所以对于一个求出的凸包无需预处理即可达到
判断线段、折线、多边形是否在凸多边形内
判断所有端点是否都在该多边形内。
判断圆是否在多边形内
两个条件,圆心在多边形内,圆心到多边形的最短距离大于等于半径,如何计算在后面有。
判断点是否在多边形内
先判断该点是否为端点或者在边上面。如果可以就能结束了。令
引一条向左的射线出来,实现可以用一个保证不在多边形内的点
判断线段是否在多边形内
有
判断折线、多边形是否在多边形内
对于每条边判断即可。
判断圆是否在圆内
对于圆
计算问题
三角形重心公式
求点到直线的距离
在直线上任取两点
求点到线段的距离
特判一下取端点问题,可以用一个类似跨立的东西判断是否取端点最优,如果不是,那么问题转化为求点到直线的距离。
求点到直线的垂足
求距离,然后随便推一推得到与向量
求两直线交点
先判断两直线是否平行或相等。如果平行,没有交点;在平行的基础上过同一点即为重合,有无数个交点。
令两条直线分别为
求直线与圆的交点
先判断不交,若圆心到直线距离大于半径则不交。算出垂足坐标,若圆心到直线距离等于半径则只有一个交点即为垂足,否则根据勾股定理,以半径为斜边,垂径为一条直角边算出偏移量,在直线上移动偏移量得到两个交点。
求三角形面积
叉积是平行四边形的面积,我们只要求任意两个边的向量的叉积除以二就是三角形面积。
求多边形面积
pick 定理
对于一个顶点在格点上的多边形,令面积为
距离
- 曼哈顿距离:
。 - 欧几里得距离:
。 - 切比雪夫距离:
。
曼哈顿距离和切比雪夫距离可以互相转化。偷懒不写。
凸包
一个包含给定点集的最小凸多边形。首先显然所有端点都被包含在点集之中。一个凸包由上下两凸壳构成。
凸壳就是把凸包切开,然后一个凸壳内的斜率单调不增(上凸壳)或单调不减(下凸壳)。
静态求凸包
不算排序的话是
以
关于维护凸壳,我们发现凸壳的斜率是单调的,所以我们维护斜率或者说这个向量和上个向量的拐向是否符合现在维护的凸壳性质,如果不是就弹出。
还有另一种不需要用到叉积自己口胡的方法:考虑凸壳的斜率具有单调性,类似斜率优化时的方法用单调栈维护斜率弹栈。这种做法会在点的纵坐标相同时出错,因为无法直接得出垂直于 x 轴的直线斜率。解决方法是对于排序后的所有
但是计算几何中往往出现更多的算法与极角相关,于是还有 极角排序求凸包。
首先视觉上处于最右下角的点一定位于凸包内,按横坐标最小或者纵坐标最小处理均可。以这个点为原点建极坐标系,以极角为第一关键字,距离为第二关键字将其他的点排序。具体实现可以通过经过原点的拐向判断哪个在极坐标系视觉上更靠下。然后按照刚才处理的方式跑一遍单调栈即可。这种做法不用求两遍凸壳,而且和某些其他计算几何算法更加适配。
带增点凸包
set 维护凸包内的点,新增点的时候判断一下在不在凸包里面,然后看能不能更新凸包,往前往后扫一下踢掉不满足凸性的点。每个点只会被加一次删一次所以还是
带增点删点离线凸包
学长说在线不是很可做。
cdq 分治,但是不会。咕咕咕。
平面最近点对
人类的智慧是无敌的
P7883 平面最近点对(加强加强版)里最高赞题解写道:
我们充分发扬人类智慧:
将所有点全部绕原点旋转同一个角度,然后按排序
根据数学直觉,在随机旋转后,答案中的两个点在数组中肯定不会离得太远
所以我们只取每个点向前的个点来计算答案
这样速度快得飞起,在时都可以在 124ms 内卡过
当然,这是对的。
分治解法
复杂度
对于一张图,按照
容易发现
正确性显然。考虑复杂度分析。对于每个点可行范围暴力更新的复杂度为
旋转卡壳
求凸包的直径。凸包的直径也可以理解成平面最远点对的距离。可以证明,对于凸包的每一条边,其与凸包点的关系是单峰的,也就是说我们可以用双指针对于每条边求出与其距离最远的点然后以这个点向两端点更新答案。
注意此时最好不要把共线的点放到凸包里面,并且特判凸包内只有两个点的情况。
半平面交
咕咕咕。
闵可夫斯基和
咕咕咕。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具