文章目录
参照文献
你谷日报真好用:https://www.luogu.com.cn/blog/wjyyy/geometry1
B站UP主:https://space.bilibili.com/88461692?spm_id_from=333.788.b_765f7570696e666f.1
https://www.cnblogs.com/xiexinxinlove/p/3708147.html
点、向量
书写约定
上了初中就应该学过直角坐标系了,这里不多阐述,本文 ( x , y ) (x,y) (x,y)表示点的坐标, A ( x , y ) A(x,y) A(x,y)中的 A A A表示点的编号,特殊的, O O O点是坐标系的圆点。
向量呢,是一个有向线段,通常表示为: A B ⃗ \vec{AB} AB就表示由 A A A到 B B B的有向线段。
但是呢,许多情况,向量默认起点是在坐标系的原点: O O O,因此向量经常看到的形式都是: O A ⃗ \vec{OA} OA,且由于起点固定,所以向量还有种表示方法,就是直接用终点 A A A来表示向量, [ x A y A ] \begin{bmatrix}x_A\\y_A\end{bmatrix} [xAyA]也是一种表示方法。
下文中一般情况下默认起点不一定在 O O O点(很大多数情况都是),但是当看到用终点表示向量时,默认起点是 O O O或者是前文规定的某个基准点(表示以这个点建立坐标系),如果一般是 A B ⃗ \vec{AB} AB这样两个端点给出的向量乘积,那么就以两个向量的共同端点为基准点建立坐标系。(当然还是有特例,一般会有特殊说明可能会忘记写)
向量的模呢,其实就是其的长度,比如向量 A ⃗ \vec{A} A的模写作: ∣ A ⃗ ∣ |\vec{A}| ∣A∣。
向量的幅角呢,其实就是其和 x x x正半轴形成的夹角。
一般可以用 a t a n 2 atan2 atan2函数进行计算,但是需要注意 C + + C++ C++用的是弧度制。(其实没啥区别,正负性没有变,值域变了而已。)
向量运算
实际上,这些运算实际指的是起点在 O O O点的运算。
普通运算
加法运算: [ x A y A ] + [ x B y B ] = [ x A + x B y A + y B ] \begin{bmatrix}x_A\\y_A\end{bmatrix}+\begin{bmatrix}x_B\\y_B\end{bmatrix}=\begin{bmatrix}x_A+x_B\\y_A+y_B\end{bmatrix} [xAyA]+[xByB]=[xA+xByA+yB]
减法运算: [ x A y A ] − [ x B y B ] = [ x A − x B y A − y B ] \begin{bmatrix}x_A\\y_A\end{bmatrix}-\begin{bmatrix}x_B\\y_B\end{bmatrix}=\begin{bmatrix}x_A-x_B\\y_A-y_B\end{bmatrix} [xAyA]−[xByB]=[xA−xByA−yB]
乘常数运算: [ x A y A ] ∗ w = [ x A ∗ w y A ∗ w ] \begin{bmatrix}x_A\\y_A\end{bmatrix}*w=\begin{bmatrix}x_A*w\\y_A*w\end{bmatrix} [xAyA]∗w=[xA∗wyA∗w]
其余的运算对于信息学计算几何用处不大,因此不再赘述。
你放屁,叉积不重要吗。
我也知道叉积重要
所以下面开始讲叉积
叉积
叉积的运算法则: [ x B y B ] ∗ [ x A y A ] = x B ∗ y A − y B ∗ x A \begin{bmatrix}x_B\\y_B\end{bmatrix}*\begin{bmatrix}x_A\\y_A\end{bmatrix}=x_B*y_A-y_B*x_A [xByB]∗[xAyA]=xB∗yA−yB∗xA(考虑到图片标识问题,所以 A B AB AB换个位置。)
你没有看错,就是这么个东西,返回值竟然还是实数,甚至还没有交换律(因此叉积一定要注意前后顺序)。
那么其有什么实际作用呢?
对于向量 O B ⃗ \vec{OB} OB和 O A ⃗ \vec{OA} OA,如果 O B ⃗ \vec{OB} OB绕 O O O点逆时针旋转 0 ° 0° 0°~ 180 ° 180° 180°能够与 O A ⃗ \vec{OA} OA共线,那么 O B ⃗ ∗ O A ⃗ > 0 \vec{OB}*\vec{OA}>0 OB∗OA>0,但是如果不能,代表 O A ⃗ \vec{OA} OA逆时针旋转 0 ° 0° 0° ~ 180 ° 180° 180°能够与 B B B重合,那么 O B ⃗ ∗ O A ⃗ < 0 , O B ⃗ ∗ O A ⃗ > 0 \vec{OB}*\vec{OA}<0,\vec{OB}*\vec{OA}>0 OB∗OA<0,OB∗OA>0,当然,如果一开始就共线,那么为 0 0 0。
至于叉积还有什么作用,也就是求 ▲ O A B ▲OAB ▲OAB的面积了。
实际上,这其实是叉积在线性代数中的意义,叉积求的是 O B ⃗ \vec{OB} OB和 O A ⃗ \vec{OA} OA为边的平行四边形的面积(除 2 2 2即可),但是为什么会有正负之分呢?额,这个跟线性变换有关,不再赘述,反正意义差不多就这两个。
额,至于证明吗,其实用几何就能证明了,至于线性代数的证明呢?我也不知道。可能根本就没有吧。
同机房的CLB奆佬用割补法给出了证明,但是实际上和上面的本质是差不多的,在此不再赘述。
当然,叉积的记忆也很简单。
交叉相乘再相减。
inline double mu(dian x,dian y,dian z)//以点z为圆点的叉积
{
double x1=(x.x-z.x),y1=(x.y-z.y),x2=(y.x-z.x),y2=(y.y-z.y);
return x1*y2-x2*y1;
}
当然,叉积有一个性质大家应该也看出来了: A ⃗ ∗ B ⃗ = − B ⃗ ∗ A ⃗ \vec{A}*\vec{B}=-\vec{B}*\vec{A} A∗B=−B∗A
多边形的面积
【题意】
在一个平面坐标系上随意画一条有n个点的封闭折线(按画线的顺序给出点的坐标),保证封闭折线的任意两条边都不相交。最后要计算这条路线包围的面积。
(注意,不能相交)
【输入格式】
第一行整数 n (3 <= n <= 1000),表示有n个点。
下来n行,每行两个整数x(横坐标)和y(纵坐标),表示点坐标(-10000<x,y<=10000)。
【输出格式】
一行一个实数,即封闭折线所包围的面积(保留4位小数)。
【样例1输入】
4
2 1
5 1
5 5
2 5
【样例1输出】
12.0000
【样例2输入】
5
2 1
5 1
3 2
5 3
2 3
【样例2输出】
4.0000
先考虑凸多边形:
只要这样子分就行了
可以看出只要选一个点然后以这个点分割成一堆三角形就行了,而且用叉积都是一个方向。
公式的话,设点的序列是从某个顶点开始,逆时针给出,为 a 1 , a 2 , a 3 , . . . , a k a_1,a_2,a_3,...,a_k a1,a2,a3,...,ak,那么就为 ( a 1 a 2 ⃗ ∗ a 1 a 3 ⃗ + a 1 a 3 ⃗ ∗ a 1 a 4 ⃗ + . . . + a 1 a k − 1 ⃗ ∗ a 1 a k ⃗ ) / 2 (\vec{a_1a_2}*\vec{a_1a_3}+\vec{a_1a_3}*\vec{a_1a_4}+...+\vec{a_1a_{k-1}}*\vec{a_1a_k})/2 (a1a2∗a1a3