算法目的
根据凸包上的边的最远点随着边逆时针转动,一起逆时针转动的性质,使用计算几何的一些方法进行旋转遍历。
算法学习
首先,这两个点一定凸包上。
很容易想到个O(n2)的算法,暴力枚举凸包上的每两点即可,想想更好的算法。
一个我证明不来的定理:
距离某个点最远的点一定在距离某个点最远的边的两端点上
所以我们循环找距离每条边上最远的点,求两次dis(边上的端点)即可
我们发现,还是O(n2)
但是画图我们可以发现,随着逆时针取边,其边所对应的最远的点也在逆时针的旋转,这就可以实现O(n)的遍历了,但是求凸包还有个O(nlogn)的过程,所以总体时间复杂度是O(nlogn)
步骤
1.求凸包
2.循环遍历凸包上的每条边,找到其最远点,并求两次dis
如何找到最远点?
叉积!!!
对于s[i],s[i+1],p[j]形成的三角形,因为叉积正比于三角形面积,而底边s[i],s[i+1]固定不变,叉积越大三角形面积越大,三角形的高越大,点到直线s[i],s[i+1]的距离越远
循环判断下一个点是否比当前点更远,如果更远就再找下一个点,直到找到为止
代码如下(求凸包过程省略)
long long getdiameter(){
if(cnt==2)return dis(s[1],s[2]);//仅有两个点
long long ans=0;
int j=3;
for(int i=1;i<=cnt;i++){
while(cross(s[i],s[i+1],s[j])<cross(s[i],s[i+1],s[j+1]))j=j%cnt+1;
ans=max(ans,max(dis(s[i],s[j]),dis(s[i+1],s[j])));
}
return ans;
}
首先,覆盖所有点等价于覆盖凸包点
其次,目标矩阵的某一条边一定与凸包上的一条边共线
循环遍历边找以这些边作为矩阵的底边找矩阵的上左右边即可
扫描二维码关注公众号,回复:
13121314 查看本文章

如何找上边?
上边就是最远点所在的平行边,旋转卡壳找即可
如何找左右边?
左边就是以该底边为x轴的最左边点所在的垂直边,可以用点积判角度找
同样的,底边逆时针转动,其对应的最左边的点也在逆时针转动
也用旋转卡壳找即可
步骤:用点积判断两个向量角度,从而判断下一个是否比当前点更靠左,如果更靠左,就再找下一个点,直到找到最做点为止