Problem Address:http://poj.org/problem?id=2187
【前言】
发现每次发解题报告都有话说= =
捡了一道需要做的旋转卡壳。
学习之。发现不是很难。
做完测试了一两组数据交之。
返回了PE。
返回的一大堆东西不知道说了什么。
然后改改交之,还是PE。
然后发现POJ上开始崩溃,PE剧增!
之后是一片PE。除了jave和pascal。
然后等到现在,发现好像开始恢复了。
交之,还是PE。
最后拿了8个PE。
最后google了一下,说distance是stl中的一个函数。
改之,交之,AC。
郁闷= =
【思路】
这道题要求点集中最远的点对的距离。
思路是求出该点集的凸包,由于最远点对必定存在于凸包上,所以由凸包计算即可得结果。
由于这道题规模比较小,暴力n^2枚举凸包上的点就可以过。
但是求最远点对可以使用旋转卡壳的方法,复杂度为O(n)。
参考网址:http://www.cyqdata.com/cnblogs/article-detail-35999
我觉得这篇文章讲得很不错。
主要思想就是,枚举所有边,对每条边求出最远点,最后记录下最大值。
由于点相对于边的单峰特性,以及其他一些性质,复杂度只是O(n)。
【代码】
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn = 50000;
struct point
{
int x;
int y;
}pt[maxn+5], q[maxn+5];
bool cmp(const point &a, const point &b)
{
int ax = a.x-pt[0].x;
int ay = a.y-pt[0].y;
int bx = b.x-pt[0].x;
int by = b.y-pt[0].y;
int t = ax*by - bx*ay;
if (t<0) return 0;
else if (t>0) return 1;
else return (ax*ax+ay*ay)<(bx*bx+by*by);
}
int get_distance(point a, point b)
{
return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
inline int cross(point a, point m, point b)
{
return (a.x-m.x)*(b.y-m.y)-(b.x-m.x)*(a.y-m.y);
}
int main()
{
int n;
int i, j, k;
point temp;
scanf("%d", &n);
for (i=0; i<n; i++)
scanf("%d %d", &pt[i].x, &pt[i].y);
for (i=1, k=0; i<n; i++)
{
if (pt[i].y<pt[k].y)
{
k = i;
}
else if (pt[i].y==pt[k].y)
{
if (pt[i].x<pt[k].x)
{
k = i;
}
}
}
temp = pt[0];
pt[0] = pt[k];
pt[k] = temp;
sort(pt+1, pt+n, cmp);
q[0] = pt[0];
q[1] = pt[1];
int top = 2;
for (i=2; i<n; i++)
{
while(top>1 && cross(q[top-2], q[top-1], pt[i])>=0)
{
top--;
}
q[top] = pt[i];
top++;
}
q[top] = q[0];
int dist = 0, t;
for (i=0, j=2; i<top; i++)
{
while(cross(q[i], q[j], q[i+1])<cross(q[i], q[j+1], q[i+1]))
{
j++;
if (j>=top)
j = 0;
}
t = get_distance(q[i], q[j]);
if (t>dist) dist = t;
}
printf("%d\n", dist);
return 0;
}