【算法笔记】计算几何之向量与叉积

前言

本来想写一篇计算几何的博客,没想到写不完了,那就写完向量吧

向量

有大小有方向的量。

向量可以理解为空间中的箭头,自一点出发,指向另一点,在数学中,向量的起始点一般是坐标原点。

因此向量可以用一个点表示(从原点指向那个点的向量)

(3,5)(3,5)表示从(0,0)(0,0)起始,指向(3,5)(3,5)的一个箭头。

向量

向量也可以理解为一个点的位移,如上图的向量即可理解为从(0,0)(0,0)移动到(3,5)(3,5)

在OI中,向量一般用一个点(x,y)(x,y)表示,方便进行叉积等计算。

1
2
3
struct Vec{
double x,y;//向量结构体
};

向量的模长

刚刚说过向量是一条箭头,模长就是箭头的长度。

A(x,y)A(x,y),则A=x2+y2|A|=\sqrt{x^2+y^2}

1
2
3
4
5
6
7
struct Vec{
double x,y;//向量结构体
double len(){
//返回模长
return sqrt(x*x+y*y);
}
};

向量的加法

如有两个向量AABB,分别表示从(0,0)(0,0)移至(1,2)(1,2)和从(0,0)(0,0)移至(3,1)(3,1)

那么A+BA+B表示什么呢?

表示先从(0,0)(0,0)位移至(1,2)(1,2),再以(1,2)(1,2)为坐标原点,移动到(3,1)(3,1)(在新的坐标系里就是(4,3)(4,3)),而这个过程中的位移是(4,3)(4,3)

向量的加法放到图像上就是把BB平移到AA上面,得到的那个点就是向量A+BA+B的终点。
向量的加法

若向量A(x1,x2)A(x_1,x_2),向量B(x2,y2)B(x_2,y_2),则A+BA+B(x1+x2,y1+y2)(x_1+x_2,y_1+y_2)

1
2
3
4
Vec operator+(Vec a,Vec b){
//向量加法
return {a.x+b.x,a.y+b.y};
}

相反向量

如果我们有一个向量A(x1,x2)A(x_1,x_2)

那它的相反向量就是A(x1,x2)-A(-x_1,-x_2)

在图像上,就是把向量AA的箭头方向取反。

相反向量
A+(A)=0A+(-A)=0,两个相反向量相加结果得0,这是显然的。

向量的减法

在了解了相反向量后,向量的减法就变得很好理解。

ABA-B,实际上就是A+(B)A+(-B),即A加上B的相反向量。

向量减法

A(x1,y1)B(x2,y2)=C(x1x2,y1y2)A(x_1,y_1)-B(x_2,y_2)=C(x_1-x_2,y_1-y_2)

1
2
3
4
Vec operator-(Vec a,Vec b){
//向量减法
return {a.x-b.x,a.y-b.y};
}

向量的点积

定义为

AB=ABcosa,bA\cdot B=|A|\cdot |B|\cos\langle a,b \rangle

即两向量模长相乘再乘上夹角的cos\cos值。

向量点积也可以写作AB=xAxB+yAyBA\cdot B=x_A\cdot x_B+y_A\cdot y_B

我们可以通过这个性质得到一些东西(因为程序中向量用点表示,而点积与夹角有关,所以可以求出关于夹角的一些问题)

1
2
3
4
double operator*(Vec a,Vec b){
//向量点积
return {a.x*b.x,a.y*b.y};
}

可以通过点积求出两向量夹角

1
return acos(a*b/(a.len()*b.len()));

向量的叉积

在线性代数里,向量可以写作一个矩阵[x1y1]\begin{bmatrix} x_1\\ y_1 \end{bmatrix}

而两个向量的乘积,就是两个向量组合到一起的行列式

[x1y1][x2y2]=[x1x2y1y2]=x1y2y1x2\begin{bmatrix} x_1\\ y_1 \end{bmatrix} \cdot \begin{bmatrix} x_2\\ y_2 \end{bmatrix}=\begin{bmatrix} x_1&x_2 \\ y_1&y_2 \end{bmatrix}=x_1y_2-y_1x_2

向量叉积的几何意义是,两个向量围成的平行四边形面积

向量叉积

证明方法很简单,割补一下就出来了

叉积证明(瞎证)

叉积的结果可能是负数,若AB=0A\cdot B=0 ,则向量A,BA,B共线,若>0>0,则说明从AA转到BB是逆时
针(BB转到AA是顺时针),若<0<0,则说明从AA转到BB是顺时针(从BB 转到AA是逆时针)

习题

求任意多边形的面积

按一定的顺序(顺、逆时针)给出一个多边形的各顶点坐标,求该多边形的面积。

思路

由于给出的坐标有顺序,我们可以相邻两个点,求两个点夹出的三角形面积。

习题1

刚刚我们学了叉积,叉积的几何意义是围成平行四边形的面积,所以那个三角形面积就是那两个点代表向量所成的叉积的一半。

这样我们就可以用叉积来求多边形面积啦!

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <bits/stdc++.h>
using namespace std;
typedef double db;
const int N=110;
struct Point{
db x,y;
db operator*(Point b){
//叉积
return x*b.y-y*b.x;
}
}p[N];
int n;
int main(){
cin>>n;
db s=0;
for(int i=1;i<=n;i++) cin>>p[i].x>>p[i].y;
for(int i=1;i<n;i++) s+=p[i]*p[i+1]/2;
s+=p[n]*p[1]/2;
printf("%.1lf",s);
}

未完待续


【算法笔记】计算几何之向量与叉积
http://luhaoren.xyz/2023/08/08/【算法笔记】计算几何之向量与叉积/
作者
luhaoren
发布于
2023年8月8日
许可协议