凸包+旋转卡壳模板——kuangbin版
凸包没什么好说的,旋转卡壳就是在一个先增再减的距离中找到极值,个人觉得还可以用三分找这个极值点,但也是仅仅加快了第一遍的速度,完全没必要。。。
胡言乱语。。。
这个速度明显不慢,三分根本没必要。
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
using namespace std;
struct Point
{
int x,y;
Point(int _x = 0, int _y = 0)
{
x = _x;
y = _y;
}
Point operator -(const Point &b)const
{
return Point(x - b.x, y - b.y);
}
int operator ^(const Point &b)const
{
return x*b.y - y*b.x;
}
int operator *(const Point &b)const
{
return x*b.x + y*b.y;
}
void input()
{
scanf("%d%d",&x,&y);
}
};
int dist2(Point a,Point b)
{
return (a-b)*(a-b);
}
int cross(Point p0,Point p1,Point p2) //计算叉积 p0p1 X p0p2
{
return (p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x);
}
const int MAXN = 50010;
Point list[MAXN];
int Stack[MAXN],top;
bool _cmp(Point p1,Point p2)
{
int tmp = cross(p1,p2,list[0]);
if(tmp > 0)return true;
else if(tmp == 0 && dist2(p1,list[0]) <= dist2(p2,list[0]))
return true;
else return false;
}
void Graham(int n)
{
Point p0;
int k = 0;
p0 = list[0];
for(int i = 1;i < n;i++)
if(p0.y > list[i].y || (p0.y == list[i].y && p0.x > list[i].x))
{
p0 = list[i];
k = i;
}
swap(list[0],list[k]);
sort(list+1,list+n,_cmp);
if(n == 1)
{
top = 1;
Stack[0] = 0;
return;
}
if(n == 2)
{
top = 2;
Stack[0] = 0;
Stack[1] = 1;
return;
}
Stack[0] = 0;
Stack[1] = 1;
top = 2;
for(int i = 2;i < n;i++)
{
while(top > 1 && (cross(list[Stack[top-1]],list[i],list[Stack[top-2]])) <= 0 )
top--;
Stack[top++] = i;
}
}
//旋转卡壳,求两点间距离平方的最大值
int rotating_calipers(Point p[],int n)
{
int ans = 0;
Point v;
int cur = 1;
for(int i = 0;i < n;i++)
{
v = p[i]-p[(i+1)%n];
while((v^(p[(cur+1)%n]-p[cur])) < 0)
cur = (cur+1)%n;
//printf("%d %d\n",i,cur);
ans = max(ans,max(dist2(p[i],p[cur]),dist2(p[(i+1)%n],p[(cur+1)%n])));
}
return ans;
}
Point p[MAXN];
int main()
{
int n;
while(scanf("%d",&n) == 1)
{
for(int i = 0;i < n;i++)
list[i].input();
Graham(n);
for(int i = 0;i < top;i++)
p[i] = list[Stack[i]];
printf("%d\n",rotating_calipers(p,top));
}
return 0;
}