一.向量
向量旋转
- 已知一个向量 p=(x,y),则其逆时针旋转A度后的向量
p = (xcosA-ysinA,ycosA+xsinA) - 同理:顺时针旋转A度后的向量
p = (xcosA+ysinA,ycosA-xsinA)
叉积和点积
什么是叉积和点积???
-
向量的叉积和点积,用来判断几何中的点线位置关系,且频繁出现,非常重要
-
叉积 = a x b = x1y2-x2y1
-
点积 = a x b = x1x2+y1y2
使用叉积
1.判断两个向量的位置关系
- 令p1=(x1,y1),p2=(x2,y2)
- 若叉积大于0,则p1逆时针旋转到p2
- 若叉积等于0,则O,p1,p2三点共线
- 若叉积小于0,则p1顺时针选择到p2
double cross(point p0,point p1,point p2){
return (p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x);
}
2.计算三角形面积
- 叉积等于该三角形面积的两倍,等于p1,p2向量构成的平行四边形面积
double area(point p0,point p1,point p2){
return fabs((p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x));
}
3.计算多面体的面积
- 原点向多面体每条边的两端点引两个向量,其向量叉积的和(不加绝对值)就是该多面体的面积的两倍。
- 给定n个点,且点的给出要是逆时针。
double cross(point p0,point p1,point p2){
return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
double area(){
point p0={0,0};
double ans=0;
for(int i=1;i<n;i++)ans+=cross(p0,p[i],p[i+1]);
ans+=cross(p0,p[n],p[1]);
return ans/2;
}
使用点积
1.判断两条直线之间的位置关系
- 令p1=(x1,y1),p2=(x2,y2)
- 若点积大于0,则p2在垂直于p1的法线右侧
- 若点积等于0,则p2垂直于p1
- 若点积小于0,则p2在垂直于p1的法线左侧
二.pick定理
-
pick定理:给定顶点均为整点的简单多边形,皮克定理说明了其面积A和内部格点数目 i,边上给点数目 b 的关系
-
A = i + b 2 \frac{b}{2} 2b - 1
-
拓展:在一个格点坐标系中,已知线段两端点的坐标分别为(x1,y1),(x2,y2)。则该线段经过的格点数为:gcd(|x1-x2|,|y1-y2|)+1
特别的,当x1=x2,经过的结点数为|y1-y2|,反之。
例题
- 问题描述:给定一个顶点均为整点的简单多边形,并逆时针给出点的坐标。求多边形内部个点的数量。
- 问题分析:使用向量叉积求出多边形面积,
使用gcd(|x1-x2|,|y1-y2|)求出线段经过的格点总数,使用pick定理即可在知道内部个点的数量。