POJ2187 Beauty Contest 凸包+旋转卡壳

本文详细介绍了如何使用旋转卡壳算法解决最小距离问题,包括思路、代码实现及优化过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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;    
}    


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值