http://poj.org/problem?id=2187
旋转卡壳算法:
所谓旋转卡壳算法是解决凸包问题的很有效的算法。下面两篇博客讲解的旋转卡壳算法很详细,我是参照这两篇博客学习的。
http://www.cnblogs.com/Booble/archive/2011/04/03/2004865.html
http://www.cnblogs.com/DreamUp/archive/2010/09/16/1828131.html
这道题是一道求平面上两点之间最大距离的问题,利用旋转卡壳算法可以很好的求解这个问题。听说可以用枚举的方法做出来,没试过,不知道快不快。
下面是我的代码:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>using namespace std;
const int maxn=50005;
struct node
{
int x,y;
bool operator <(node a)const
{
if(y==a.y) return x<a.x;
return y<a.y;
}
}point[maxn];int n;
int s[maxn];
int top;//计算叉积
double det(double x1,double y1,double x2,double y2)
{return x1*y2-x2*y1;}//计算两点之间的距离公式
int dist(node a,node b)
{return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);}//根据叉积计算两向量的位置关系
double cross(node a,node b,node c)
{return det(b.x-a.x,b.y-a.y,c.x-a.x,c.y-a.y);}//判断double型数据与0的大小关系
int dblcmp(double x)
{
if(fabs(x)<1e-6) return 0;
return x>0?1:-1;
}//Graham算法模板
void Graham()
{
top=-1;
s[++top]=0;
s[++top]=1;
for(int i=2;i<n;i++)
{
while(top>=1 && dblcmp(cross(point[s[top-1]],point[i],point[s[top]]))>=0)
top--;
s[++top]=i;
}
int temp=top;
s[++top]=n-2;
for(int i=n-3;i>=0;i--)
{
while(top>=temp+1 && dblcmp(cross(point[s[top-1]],point[i],point[s[top]]))>=0)
top--;
s[++top]=i;
}
}int fun()
{
int q=1;
int ans=0;
for(int i=0;i<n;i++)
{
//根据两个三角形面积的大小来更新点
while(dblcmp(cross(point[s[i+1]],point[s[q]],point[s[i]])-cross(point[s[i+1]],point[s[q+1]],point[s[i]]))<0)
q=(q+1)%top;
//找到两点间的最大距离
ans=max(ans,max(dist(point[s[q]],point[s[i+1]]),dist(point[s[q]],point[s[i]])));
}
return ans;
}int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d%d",&point[i].x,&point[i].y);
sort(point,point+n);
//利用Gramham算法求凸包
Graham();
//在求解的凸包中求卡壳
int ans=fun();
printf("%d\n",ans);
//system("pause");
return 0;
}