学习笔记:旋转卡壳
参考博客
例题
- 洛谷 P1452 Beauty Contest
参考代码
const int MAXN = 50005;
const double EPS = 1E-8;
inline int dcmp(double x)
{
if (fabs(x) < EPS) return 0;
else return x > 0 ? 1 : -1;
}
struct Vector
{
double x,y;
Vector(double _x = 0,double _y = 0) : x(_x),y(_y) {}
friend bool operator <(const Vector &VecA,const Vector &VecB)
{
if (VecA.x < VecB.x || (VecA.x == VecB.x && VecA.y < VecB.y)) return true;
else return false;
}
friend Vector operator -(const Vector &VecA,const Vector &VecB)
{
return Vector(VecA.x - VecB.x,VecA.y - VecB.y);
}
friend double operator ^(const Vector &VecA,const Vector &VecB)
{
return VecA.x * VecB.y - VecA.y * VecB.x;
}
friend double dis(const Vector &VecA,const Vector &VecB)
{
return (VecA.x - VecB.x) * (VecA.x - VecB.x) + (VecA.y - VecB.y) * (VecA.y - VecB.y);
}
}pos[MAXN],Stack[MAXN];
int n,top;
double ans;
void getHull()
{
for (int i = 0;i <= n - 1;++i)
{
while (top >= 2 && dcmp((Stack[top - 1] - Stack[top - 2]) ^ (pos[i] - Stack[top - 1])) <= 0) top--;
Stack[top++] = pos[i];
}
int c = top;
for (int i = n - 2;i >= 0;--i)
{
while (top >= c + 1 && dcmp((Stack[top - 1] - Stack[top - 2]) ^ (pos[i] - Stack[top - 1])) <= 0) top--;
Stack[top++] = pos[i];
}
}
void getMax()
{
int j = 2;//第三个点。因为Stack[]是0基准的。
for (int i = 0;i <= top - 2;++i)
{
while (((Stack[i + 1] - Stack[i]) ^ (Stack[j] - Stack[i + 1])) < ((Stack[i + 1] - Stack[i]) ^ (Stack[j + 1] - Stack[i + 1])))
j = (j + 1) % (top - 2);
ans = max(ans,max(dis(Stack[j],Stack[i]),dis(Stack[j],Stack[i + 1])));
}
printf("%.0lf",ans);
}
void init()
{
scanf("%lld",&n);
for (int i = 0;i <= n - 1;++i) scanf("%lf%lf",&pos[i].x,&pos[i].y);
sort(pos,pos + n);
}
void work()
{
getHull();
getMax();
}
我们枚举凸包上所有的边(实际上是两个端点,for (int i = 0;i <= top - 2;++i)
),对于每条边,找到凸包上其他的点到这条边的距离最大值。
以边为例计算点到直线的距离:
- ,直线方程为,点的坐标为。
- 利用向量叉积,由于平行四边形的一条边()是已知的,可以通过比较和组成的向量和向量的叉积,来比较它们到当前边的距离。
while ((Stack[i + 1] - Stack[i]) ^ (Stack[j] - Stack[i + 1])) < ((Stack[i + 1] - Stack[i]) ^ (Stack[j + 1] - Stack[i + 1]))
j = (j + 1) % (top - 2);//防止溢出。
若有更优,更新即可。
根据top
的定义,图中top
的值为8,但实际上组成凸包的点一共只有top - 2 = 6
个。所以,当j
枚举到7时,应对top - 2
取模。