zxy巨巨
神仙
ak了winter camp回来给我们讲知识点
开始吧
计算及处理几何问题尽量减小误差
涉及到double,计算少用除法、开根(牛顿迭代法三次除法)
精度:
妙啊
向量表示线段(有向线段)
还可以用美丽的文玉的方法
对
于
∀
C
∈
A
B
,
∃
p
∈
[
0
,
1
]
,
C
=
p
A
+
(
1
−
p
)
B
对于\forall C\in AB,\exists p\in [0,1],C=pA+(1-p)B
对于∀C∈AB,∃p∈[0,1],C=pA+(1−p)B
一个方法
直线方程 A x + B y + C = 0 Ax+By+C=0 Ax+By+C=0可以用
向量
struct vec{
double x,y;
};
vec operator+(const vec a,const vec b){
return (vec){a.x+b.x,a.y+b.y};
}
vec a,b,c;
a.x=in,a.y=in,b.x=in,b.y=in;
c=a+b;
printf("%lf %lf",c.x,c.y);
return 0;
重载运算符是个好东西
但是你要用就用你重载的东西啊!(定义了+不要有-)
重载后不影响原来对于其他数据类型的用法
函数也可以解决这个问题
点积
详见数学书,必修四欢迎您
叉乘
叉乘结果的大小是两向量构成的平行四边形的有向面积,用行列式算(详见线形代数)(证明显然)
方向利用右手定则判断(你发现你比good的时候就是正的,比bad的时候就是负的)
向量的叉乘有有序性,不满足交换律
a
⃗
×
b
⃗
=
−
b
⃗
×
a
⃗
\vec a\times \vec b=-\vec b\times \vec a
a×b=−b×a
(期末考前玩着玩着搞出来了向量叉乘坐标运算的一个严格的证明,我是不是有点不务正业T_T)
向量叉乘坐标运算:
仿照数学书上点乘的坐标运算,我们需要知道向量的叉乘是否遵循分配率
即
(
a
⃗
+
b
⃗
)
×
c
⃗
=
?
=
a
⃗
×
c
⃗
+
b
⃗
×
c
⃗
(\vec{a}+\vec{b})\times\vec{c}=?=\vec{a}\times\vec{c}+\vec{b}\times \vec{c}
(a+b)×c=?=a×c+b×c
做出几何图形如下,易证
(
a
⃗
+
b
⃗
)
×
c
⃗
=
S
A
C
C
′
D
(\vec{a}+\vec{b})\times\vec{c}=S_{ACC'D}
(a+b)×c=SACC′D
a
⃗
×
c
⃗
=
S
A
B
B
′
D
\vec{a}\times\vec{c}=S_{ABB'D}
a×c=SABB′D
b
⃗
×
c
⃗
=
S
B
C
C
′
B
′
\vec{b}\times\vec{c}=S_{BCC'B'}
b×c=SBCC′B′
由初中几何知识易知:
(
a
⃗
+
b
⃗
)
×
c
⃗
=
a
⃗
×
c
⃗
+
b
⃗
×
c
⃗
(\vec{a}+\vec{b})\times\vec{c}=\vec{a}\times\vec{c}+\vec{b}\times \vec{c}
(a+b)×c=a×c+b×c
接着,我们就可以放心大胆地使用分配率了(下面有点不严谨:
i
和
j
i和j
i和j上面应该打向量的箭头,但是咕了)
a
⃗
=
(
x
1
,
y
1
)
=
x
1
i
+
y
1
j
,
b
⃗
=
(
x
2
,
y
2
)
=
x
2
i
+
y
2
j
\vec{a}=(x_1,y_1)=x_1i+y_1j,\ \vec{b}=(x_2,y_2)=x_2i+y_2j
a=(x1,y1)=x1i+y1j, b=(x2,y2)=x2i+y2j
a
⃗
×
b
⃗
=
x
1
x
2
(
i
×
i
)
+
y
1
y
2
(
j
×
j
)
+
x
1
y
2
(
i
×
j
)
+
y
1
x
2
(
j
×
i
)
\vec{a}\times\vec{b}=x_1x_2(i\times i)+y_1y_2(j\times j)+x_1y_2(i\times j)+y_1x_2(j\times i)
a×b=x1x2(i×i)+y1y2(j×j)+x1y2(i×j)+y1x2(j×i)
=
x
1
y
2
−
x
2
y
1
=x_1y_2-x_2y_1
=x1y2−x2y1(ixi=0,jxj=0,ixj=1,jxi=-1)
妙不妙?
向量的旋转
a
⃗
=
(
x
,
y
)
=
x
i
⃗
+
y
j
⃗
\vec a=(x,y)=x\vec i+y\vec j
a=(x,y)=xi+yj
旋转角
θ
\theta
θ
各位应该很明显的看到直接把
x
i
⃗
x\vec i
xi和
y
j
⃗
y\vec j
yj转了不就行了?
叉乘
我是不是又打了一个一样的标题?
那是因为我懒得想这个标题究竟应该写什么
· 点乘和叉乘用
void dottimes(vec a,vec b,int &c){
c=a.x*b.x+a.y*b.y;
}
void crosstimes(vec a,vec b,int &c){
c=a.x*b.y-b.x*a.y;
}
给一点叉乘的小结论
· 求有向面积:废话,用叉乘
S
Δ
O
A
B
=
O
A
⃗
×
O
B
⃗
S_{\Delta OAB}=\vec {OA}\times \vec {OB}
SΔOAB=OA×OB
· 又看数学书:三点共线的时候是不是围成三角形的面积为0?是的,可以根据叉乘 x 1 y 2 − x 2 y 1 = 0 x_1y_2-x_2y_1=0 x1y2−x2y1=0
· 还可以依据三角形的有向面积判断角的大小(优劣角)——
称
α
\alpha
α为以
a
⃗
\vec a
a为始边、以
b
⃗
\vec b
b为终边的角
可以发现:
a
⃗
×
b
⃗
>
0
⇒
α
∈
(
0
,
π
)
\vec a\times \vec b\gt0\Rightarrow\alpha\in(0,\pi)
a×b>0⇒α∈(0,π)
a
⃗
×
b
⃗
<
0
⇒
α
∈
(
π
,
2
π
)
\vec a\times \vec b\lt0\Rightarrow\alpha\in(\pi,2\pi)
a×b<0⇒α∈(π,2π)
一会儿会用到它来做凸包
· 另:点乘的正负由 c o s < a ⃗ , b ⃗ > cos<\vec a,\vec b> cos<a,b>提供,因此可以判断夹角为钝角或锐角
· 求距离:三角形面积与高,他不容易吗?
d
=
S
Δ
P
A
B
∣
A
B
⃗
∣
=
O
A
⃗
×
O
B
⃗
2
∣
A
B
⃗
∣
d=\frac{S_{\Delta PAB}}{|\vec {AB}|}=\frac{\vec {OA}\times \vec {OB}}{2|\vec {AB}|}
d=∣AB∣SΔPAB=2∣AB∣OA×OB
提醒!叉乘算的是平行四边形的面积!
· 判断是否相交:
端点分布在两侧,利用面积,叉乘的结果同号(注意边的顺序)
还可以用来求交点——知道面积知道面积比知道边上比例
· 点与多边形的关系:在内或在外
做一条直线,记穿边的个数,奇内偶外
如果交了顶点,算远不算近(不要问我,对于顶点肯定不能说交了1个点对吧,那么交0个或者交2个对奇偶性是没有影响的,算不算无所谓)
· 求多边形面积就很妙了
叉乘自动给你改变正负
这就是向量的魅力,所以我第一眼看到向量的时候就爱上他了
· 还有一种判断点是否在多边形的方法
把多边形放在极坐标系里,以一个点作为原点,易知每条对角线的极角是单增的,知道点的极角,二分它所在的区域,再用叉乘判断点在不在里面就行了
【模板】二维凸包 / [USACO5.1]圈奶牛Fencing the Cows
求凸包:
step1 取极点,选左下角的那个
step2 排序,根据极角单增与距离单增(叉乘实现)
step3 挨个连,用栈维护,弹优角
现在栈里面就是凸包的边界了
码的时候遇到了一点问题:
运算符之类的符号是不能对结构体运行
在结构体里面要么重载运算符,要么return true(不改变顺序)| return false(改变顺序)