计算几何

计算几何

内容太多(105 页 ppt 呢
故只写大纲和之前不知道的东西

基本模板

前置知识

向量

  • 基本运算(加减、数乘、点乘、叉乘)
  • 高维向量的运算
  • 相关计算(长度、夹角、面积……

  • 叉乘:a×b=|a||b|sin<a,b>
    • 角度是有向的(从 a 转到 b
    • 几何意义:平行四边形的有向面积
    • 二维坐标计算:a×b=xaybyaxb
  • n 维 n-1 个向量叉乘,结果是 n 维向量,系数是行列式
    |x1x2iy1y2jz1z2k|
    • 二维:u×u=(yu,xu)
    • 三维:方向是法向量,大小是平四面积

基于向量的表示法

  • p
  • 直线 (p,d)p 是任意一点,d 是方向(一般用单位向量)
  • 线段 (p,d)p 是一个端点,dp 到另一个端点的位移
  • 多边形 (p1,p2,,pn),一般逆时针记录端点
  • (o,r)
  • 曲线:解析式

图形关系

点线

  • u 在直线上:(up)×d=0
  • u 在线段上:在直线上 & 横纵坐标在区间内
  • u,v 在直线同侧:((up)×d)×((vp)×d)>0

线线

平行

  • l1l2d1×d2=0
  • l1l2 重合:平行且 p2l1

相交

  • 快速排斥实验 & 跨立实验:判断线段是否有交
  • 求直线的交点:列直线方程代入求解u=p1+kd1
    k=(p2p1)×d2d1×d2

点 & 多边形

  • 先判去点在多边形边缘的情况
  • 从该点引出任意一条射线,统计与多边形相交的次数。若奇数,则点在多边形内
  • 对于射线经过多边形某边或某点的情况,规定射线上的点均在射线的同一侧

直线 & 圆

  • 圆心到直线距离判位置关系
  • 过圆心的垂线 (o,d×d),求交得到垂足
  • 勾股算交点到垂足距离

圆圆

  • 圆心距离判位置关系
  • 交线方程 线圆交点

基本计算

  • 点到直线距离 dis(u,(p,d))=(up)×d
  • 多边形面积:12|pi×p(imodn)+1|,绝对值在求和号外面
  • 旋转向量 (a×(sinθ,cosθ),a(sinθ,cosθ)),θ[0,π]

极角排序

先判象限,同一象限按 u×v 的正负判断。

int quadrant(const vector2d& u) {
return (u.y < 0) << 1 | ((u.x < 0) ^ (u.y < 0));
}
bool polar_cmp(const vector2d& u, const vector2d& v) {
int qu = quadrant(u);
int qv = quadrant(v);
if (qu != qv) return qu < qv;
ll d = det(u, v);
if (d) return d > 0;
return norm2(u) < norm2(v);
}

二维凸包

Andrew 算法

  • 所有点按 x 为第一关键字,y 为第二关键字排序
  • 单调栈分别求上下凸壳
vector<poi> Andrew(vector<poi> p){
vector<poi> q;int tl=0;
sort(p.begin(),p.end());
rep(i,0,p.size()-1){
while(tl>1 && cross(q[tl-2],q[tl-1],p[i])<=0)
q.pop_back(),--tl;
q.push_back(p[i]);++tl;
}
int tmp=tl;
per(i,p.size()-2,0){
while(tl>tmp && cross(q[tl-2],q[tl-1],p[i])<=0)
q.pop_back(),--tl;
q.push_back(p[i]);++tl;
}
q.pop_back();return q;
}

Graham 算法

  • 钦定一个起点,所有点极角排序
  • 同样是单调栈
  • 一般不写

例题 [SHOI2012] 信用卡凸包

普通凸包板子 + 角上转一圈

闵可夫斯基和

另一类图形并(?

定义 C={a+b|aA,bB}

从左下角开始,双指针扫,按照极角序依次加入每条边

vector<poi> minkowski(vector<poi> &a,vector<poi> &b){
vector<poi> c{a[0]+b[0]};int pa=1,pb=1;
a.push_back(a[0]),b.push_back(b[0]);
while(pa<(int)a.size() || pb<(int)b.size()){
if(pa<(int)a.size() && (pb==(int)b.size()||
sgn((a[pa]-a[pa-1])^(b[pb]-b[pb-1]))>=0))
c.push_back(c.back()+a[pa]-a[pa-1]),pa++;
else c.push_back(c.back()+b[pb]-b[pb-1]),pb++;
}
return c;
}

例题 [JSOI2018] 战争

题目要判断是否存在 q+v=p
移项得 v=pq
于是判断 v 是否在 p,q 的闵可夫斯基和内
钦定起点,二分极角得到 v 对应边,判断是否和起点在同一方向

旋转卡壳

在枚举凸包的边的同时,维护其他需要的点

可以在线性复杂度内解决凸包直径、最小矩形覆盖等问题

例题 [HNOI2007] 最小矩形覆盖

结论:最小矩形覆盖一定包含凸包上的一条边

枚举这条边,维护 3 个最远点即可

注意初始最左边的点要先赋值成初始最右边的点再扫,否则动不了

半平面

一条直线和直线的一侧,包含直线为闭,不包含为开

定义:Ax+By+C0

在计算几何中用向量表示,统一为向量的左侧

半平面交

  • 加入边界(避免特判无穷大)
  • 极角排序(斜率相同,靠左的在前面)+ 去重
  • 单调队列维护(先弹队尾,再弹队首)
    • 弹出条件(以队尾为例)

      队尾的两直线交点在新直线右侧时,弹出队尾。
    • 改进精度(代入交点坐标,解方程,去分母)
    • ((p1p3)×d3)(d1×d2)((p1p2)×d2)(d1×d3)
    • 先弹队尾,再弹队首,全部结束后用队首弹队尾

  • 判断无交
    • 若最后只有 <2 条线,一定无交
    • 任取两条线的交点,判断它是否在所有射线的左边
    • 特殊情况:存在平行且反向,互相在对方右侧的向量
      如果出现,其他向量一定被弹没,只需判断队尾和前一个即可
  • 求面积就是平凡的多边形

随机增量法

增量法:将一个问题化为刚好小一层的子问题
T(n)=T(n1)+g(n)

例题:Luogu 1742 最小圆覆盖

  • 求三个点的外接圆:垂直平分线
  • 增量构造
    • 前 i-1 个点的圆是 C,若 i 在 C 中,跳过
    • 否则 i 一定在新的 C
    • 重复找第一个不在圆 C 中的点,让圆 C 过这个点
  • 感性理解,最后一定能构造出前 i 个点的圆,因为不会出现两个点在 i “两端”的情况(否则 i 就在 C 中)
  • 复杂度分析:
    • 由于最多只有 3 个点参与确定了最小覆盖圆,每个点参与的概率不大于 3n,也就是每层会循环到下一层的概率不大于 3i
    • T1(n)=O(n)+3iT2(i)
    • T2(n)=O(n)+3iT3(i)
    • T3(n)=O(n)
    • 显然 T1(n)=T2(n)=T3(n)=O(n),带有一个大概 13 的常数

平面图转对偶

定义:原图每个面对应一个点,每条边左右的面连起来。

(虽然很丑但它是对偶图/kk

  • 认为每个面是由逆时针的有向边拼起来的
  • 原图中的边拆成两条有向边(对应两个面)
  • 枚举每条边,若还没访问过,就从它出发逆时针转,找原图中它左边的面
  • 对原图中每个点,从它出发的有向边极角排序
  • 下一个要访问的边,就是当前边的反向边在极角序中的前驱
  • 最后连接每条边对应的两个面

例题:Luogu 3249 矿区

先转对偶图,随便找一颗生成树,以无界域为根

非常厉害的结论:

多边形边界对应的树边,若内部是儿子,加上子树权值;否则,减去子树权值

画图可以感受到这个容斥是正确的,并适用于一切可加减的信息

习题

Luogu 3517 WYK-Plot

给定 n 个点,要求分成不超过 m 段,最小化每段最小覆盖圆的半径最大值。

二分答案,关键在于 check

我们不可以按顺序增量构造,因为随机增量复杂度才是对的。

从左到右构造,每个左端点找最大右端点,如果二分范围 [l,n],复杂度会悲催的成为 O(n2logn)

key: 倍增优化二分

考虑倍增段长找到第一个不符合要求的 R,如果最终答案为 r,显然倍增的复杂度不超过 2(rl)

[l,R] 区间来二分,check 的复杂度就是 O(nlogn) 了。

加上二分答案的复杂度,最终复杂度是 O(nlog2n)

posted @   Cindy_Li  阅读(24)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示