前言
本来想写一篇计算几何的博客,没想到写不完了,那就写完向量吧
向量
有大小有方向的量。
向量可以理解为空间中的箭头,自一点出发,指向另一点,在数学中,向量的起始点一般是坐标原点。
因此向量可以用一个点表示(从原点指向那个点的向量)
如(3,5)表示从(0,0)起始,指向(3,5)的一个箭头。

向量也可以理解为一个点的位移,如上图的向量即可理解为从(0,0)移动到(3,5)
在OI中,向量一般用一个点(x,y)表示,方便进行叉积等计算。
1 2 3
| struct Vec{ double x,y; };
|
向量的模长
刚刚说过向量是一条箭头,模长就是箭头的长度。
若A(x,y),则∣A∣=x2+y2
1 2 3 4 5 6 7
| struct Vec{ double x,y; double len(){ return sqrt(x*x+y*y); } };
|
向量的加法
如有两个向量A和B,分别表示从(0,0)移至(1,2)和从(0,0)移至(3,1)。
那么A+B表示什么呢?
表示先从(0,0)位移至(1,2),再以(1,2)为坐标原点,移动到(3,1)(在新的坐标系里就是(4,3)),而这个过程中的位移是(4,3)。
向量的加法放到图像上就是把B平移到A上面,得到的那个点就是向量A+B的终点。

若向量A(x1,x2),向量B(x2,y2),则A+B为(x1+x2,y1+y2)。
1 2 3 4
| Vec operator+(Vec a,Vec b){ return {a.x+b.x,a.y+b.y}; }
|
相反向量
如果我们有一个向量A(x1,x2)
那它的相反向量就是−A(−x1,−x2)
在图像上,就是把向量A的箭头方向取反。

A+(−A)=0,两个相反向量相加结果得0,这是显然的。
向量的减法
在了解了相反向量后,向量的减法就变得很好理解。
如A−B,实际上就是A+(−B),即A加上B的相反向量。

A(x1,y1)−B(x2,y2)=C(x1−x2,y1−y2)
1 2 3 4
| Vec operator-(Vec a,Vec b){ return {a.x-b.x,a.y-b.y}; }
|
向量的点积
定义为
A⋅B=∣A∣⋅∣B∣cos⟨a,b⟩
即两向量模长相乘再乘上夹角的cos值。
向量点积也可以写作A⋅B=xA⋅xB+yA⋅yB
我们可以通过这个性质得到一些东西(因为程序中向量用点表示,而点积与夹角有关,所以可以求出关于夹角的一些问题)
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]
而两个向量的乘积,就是两个向量组合到一起的行列式
[x1y1]⋅[x2y2]=[x1y1x2y2]=x1y2−y1x2
向量叉积的几何意义是,两个向量围成的平行四边形面积

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

叉积的结果可能是负数,若A⋅B=0 ,则向量A,B共线,若>0,则说明从A转到B是逆时
针(B转到A是顺时针),若<0,则说明从A转到B是顺时针(从B转到A是逆时针)
习题
求任意多边形的面积
按一定的顺序(顺、逆时针)给出一个多边形的各顶点坐标,求该多边形的面积。
思路
由于给出的坐标有顺序,我们可以相邻两个点,求两个点夹出的三角形面积。

刚刚我们学了叉积,叉积的几何意义是围成平行四边形的面积,所以那个三角形面积就是那两个点代表向量所成的叉积的一半。
这样我们就可以用叉积来求多边形面积啦!
代码
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); }
|
未完待续