前言
东西好多啊 ⋯ \cdots ⋯还好都不算难
向量的基本表示与运算
向量的定义:可以理解成只有方向和长度,没有位置的量(亦称矢量)
向量的表示:在平面几何中表示为 A B → \overrightarrow{AB} AB,但在程序中一般用平面直角坐标系表示法,即 向量 P ( x 1 , y 1 ) P(x_1,y_1) P(x1,y1)代表从原点指向 P P P的向量。用这种定义,显然从 A ( x a , y a ) A(x_a,y_a) A(xa,ya)指向 B ( x b , y b ) B(x_b,y_b) B(xb,yb)的向量等价于向量 Q ( x b − x a , y b − y a ) Q(x_b-x_a,y_b-y_a) Q(xb−xa,yb−ya)。
P S . PS. PS.零向量确实存在,即 0 → \overrightarrow{0} 0,大小为 0 0 0,方向为任意方向
向量的加减:向量的加减 ⟺ \iff ⟺坐标的加减,即 P ( x 1 , y 1 ) ± Q ( x 2 , y 2 ) = R ( x 1 ± x 2 , y 1 ± y 2 ) P(x_1,y_1)\pm Q(x_2,y_2)=R(x_1\pm x_2,y_1\pm y_2) P(x1,y1)±Q(x2,y2)=R(x1±x2,y1±y2)显然向量的加减满足交换律、结合律。
向量的叉乘: P ( x 1 , y 1 ) × Q ( x 2 , y 2 ) = x 1 y 2 − x 2 y 1 P(x_1,y_1)\times Q(x_2,y_2)=x_1y_2-x_2y_1 P(x1,y1)×Q(x2,y2)=x1y2−x2y1叉乘的核心用途为判断位置关系,即若 P × Q < 0 P\times Q<0 P×Q<0则 P P P在 Q Q Q逆时针方向,反之若 P × Q 》 0 P\times Q》0 P×Q》0则 P P P在 Q Q Q顺时针方向,若 P × Q = 0 P\times Q=0 P×Q=0则 P , Q P,Q P,Q共线(但不知道是否同向)。显然向量的叉乘结果为一个数且不满足交换律。
接下来依次讨论两个东西的位置关系(点、线段、矩形、圆、多边形 ⋯ \cdots ⋯)
点与矩形
点为 P ( x 0 , y 0 ) P(x_0,y_0) P(x0,y0),矩形左下顶点与右上顶点分别为 A ( x 1 , y 1 ) , B ( x 2 , y 2 ) A(x_1,y_1),B(x_2,y_2) A(x1,y1),B(x2,y2)
点在矩形内: x 1 ≤ x 0 ≤ x 2 x_1\le x_0\le x_2 x1≤x0≤x2且 y 1 ≤ y 0 ≤ y 2 y_1\le y_0\le y_2 y1≤y0≤y2
复杂度 O ( 1 ) O(1) O(1)
点与线段
点为 P ( x 0 , y 0 ) P(x_0,y_0) P(x0,y0),线段两端点分别为 A ( x 1 , y 1 ) , B ( x 2 , y 2 ) A(x_1,y_1),B(x_2,y_2) A(x1,y1),B(x2,y2)
点在线段上: A P → × A B → = 0 \overrightarrow{AP}\times \overrightarrow{AB}=0 AP×AB=0且 x 1 ≤ x 0 ≤ x 2 x_1\le x_0\le x_2 x1≤x0≤x2且 y 1 ≤ y 0 ≤ y 2 y_1\le y_0\le y_2 y1≤y0≤y2
复杂度 O ( 1 ) O(1) O(1)
线段与线段
两条线段两端点分别为 A ( x 1 , y 1 ) A(x_1,y_1) A(x1,y1)与 B ( x 2 , y 2 ) B(x_2,y_2) B(x2,y2)、 M ( x 3 , y 3 ) M(x_3,y_3) M(x3,y3)与 N ( x 4 , y 4 ) N(x_4,y_4) N(x4,y4)
线段与线段相交: ( A M → × A B → ) ∗ ( A N → × A B → ) ≤ 0 (\overrightarrow{AM}\times \overrightarrow{AB})*(\overrightarrow{AN}\times \overrightarrow{AB})\le0 (AM×AB)∗(AN×AB)≤0且 ( M A → × M N → ) ∗ ( M B → × M N → ) ≤ 0 (\overrightarrow{MA}\times \overrightarrow{MN})*(\overrightarrow{MB}\times \overrightarrow{MN})\le0 (MA×MN)∗(MB×MN)≤0
复杂度 O ( 1 ) O(1) O(1)
注意特判平行和首尾相接
射线、直线均可类比求得(更简单)
点与多边形
点为 P ( x 0 , y 0 ) P(x_0,y_0) P(x0,y0),多边形有 n n n条边
点在多边形内:过点 P P P引一条平行于坐标轴的射线,枚举每条边求交点数,交点数之和为奇数则在多边形内,反之不在。
复杂度 O ( n ) O(n) O(n)
注意特判平行和交于顶点
线段与多边形
线段两端点分别为 A ( x 1 , y 1 ) , B ( x 2 , y 2 ) A(x_1,y_1),B(x_2,y_2) A(x1,y1),B(x2,y2),多边形有 n n n条边
线段在多边形内: A A A在多边形内且 B B B在多边形内且 A B AB AB与多边形无内交点(枚举求得)
复杂度 O ( n ) O(n) O(n)
注意特判内交与平行
P S . PS. PS.老师有复杂度 O ( n l o g n ) O(nlogn) O(nlogn)但不用特判的做法,不过个人感觉没必要。
多边形与多边形
这个反而简单
两个多边形分别有 n n n、 m m m条边
多边形在多边形内:依次判断每条边是否在另一多边形内即可
复杂度 O ( n m ) O(nm) O(nm)
点与圆
点为 P ( x 1 , y 1 ) P(x_1,y_1) P(x1,y1),圆心为 O ( x 0 , y 0 ) O(x_0,y_0) O(x0,y0),半径为 r r r
点在圆内: P O < r PO<r PO<r,若想避免精度误差就用 ( x 0 − x 1 ) 2 + ( y 0 − y 1 ) 2 < r 2 (x_0-x_1)^2+(y_0-y_1)^2<r^2 (x0−x1)2+(y0−y1)2<r2
复杂度 O ( 1 ) O(1) O(1)
线段与圆
圆是凸的
线段两端点分别为 A ( x 1 , y 1 ) , B ( x 2 , y 2 ) A(x_1,y_1),B(x_2,y_2) A(x1,y1),B(x2,y2),圆心为 O ( x 0 , y 0 ) O(x_0,y_0) O(x0,y0),半径为 r r r
线段在圆内: ( x 0 − x 1 ) 2 + ( y 0 − y 1 ) 2 < r 2 (x_0-x_1)^2+(y_0-y_1)^2<r^2 (x0−x1)2+(y0−y1)2<r2且 ( x 0 − x 2 ) 2 + ( y 0 − y 2 ) 2 < r 2 (x_0-x_2)^2+(y_0-y_2)^2<r^2 (x0−x2)2+(y0−y2)2<r2(即端点都在圆内)
复杂度 O ( 1 ) O(1) O(1)
多边形与圆
圆是凸的
多边形有 n n n条边,圆心为 O ( x 0 , y 0 ) O(x_0,y_0) O(x0,y0),半径为 r r r
多边形在圆内:等价于顶点都在圆内(枚举判断)
复杂度 O ( n ) O(n) O(n)
圆在多边形内:避免不了精度误差了最暴力的求
O
O
O到多边形每条边的端点的距离、用"垂直的一次函数斜率之积为
−
1
-1
−1"求解
O
O
O到该边的垂直距离(如果垂足在线段上的话),求最小值与
r
r
r比较
复杂度 O ( n ) O(n) O(n)
细节很多
圆与圆
圆心分别为 O 1 ( x 1 , y 1 ) O_1(x_1,y_1) O1(x1,y1)、 O 2 ( x 2 , y 2 ) O_2(x_2,y_2) O2(x2,y2),半径为 r 1 r_1 r1、 r 2 r_2 r2
圆在圆内: O 1 O 2 < r 1 − r 2 O_1O_2<r_1-r_2 O1O2<r1−r2
圆与圆相交: r 1 − r 2 < O 1 O 2 < r 1 + r 2 r_1-r_2<O_1O_2<r_1+r_2 r1−r2<O1O2<r1+r2
圆与圆相离: O 1 O 2 > r 1 + r 2 O_1O_2>r_1+r_2 O1O2>r1+r2
复杂度 O ( 1 ) O(1) O(1)
特判边界
凸包
定义:形象的将,在木板上有n个钉子,拿根牛皮筋从无限远处开始收缩,问最后成了什么样(可能问周长或面积)
这里只讲单调链算法
对所有点进行 x − y x-y x−y从小到大排序(以 x x x为第一关键字,以 y y y为第二关键字)
从最左下点开始维护一个栈,按顺序扫描,当碰到一个新的点时,判断这个点是否在栈顶 2 2 2个点形成的线段的顺时针方向,若是,则弹出栈顶,加入该点,否则不加。
做到最后一个点时,栈中的点就是该凸包的下凸壳,再反向搜一遍求出上凸壳即可。