计算几何练习3

最远点对

【题目描述】:

给定平面上N个点的坐标,找出距离最远的两个点。

【输入描述】:

第一行一个N,表示平面上的点数。

以下N行,每行一个x和y,表示一个点的横坐标和纵坐标。

【输出描述】:

仅输出最远点对的距离,精确到小数点后两位。

【样例输入】:

8
2720 -443
46 -2422
-2077 -1346
4520 -4963
-1791 1547
-1262 4025
-2997 913
-1667 -2499

【样例输出】:

10687.17

【时间限制、数据范围及描述】:

时间:1s 空间:128M

N<=100,000; -10000<=x,y<=10000

其实这题只需在凸包的基础上加一个搜索就可以了。我们将这些点的凸包坐标找出来,然后在这些坐标中搜索一对最远的点对即可。另:搜索的过程中可以用旋转卡壳的算法进行优化,但这里我就直接暴力求解。

AC代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath> 
#define ll long long
using namespace std;
ll ox,oy,maxn;
double ansn; 
struct node{
	ll x,y;
	node(){x=0;y=0;}
	node(int a,int b){x=a;y=b;}
	node(const node &p1){x=p1.x;y=p1.y;}
	node operator = (const node &a){
		x=a.x;y=a.y;
		return *this;
	}
};
ll operator *(const node & a,const node & b){
	ll xx1=(a.x-ox)*(b.y-oy),xx2=(a.y-oy)*(b.x-ox);
	return xx1-xx2;
}
ll mx(ll x,ll y){
	return x>y?x:y; 
} 
bool operator <(const node &a,const node &b){
	ll x;
	x=a*b;
	if(x>0)return 1;
	if(x==0){
		if((a.x-ox)*(a.x-ox)+(a.y-oy)*(a.y-oy)<(b.x-ox)*(b.x-ox)+(b.y-oy)*(b.y-oy))return 1;
	}
	return 0;
}
bool comp(const node &a,const node &b){
	if((a.x-ox)*(a.x-ox)+(a.y-oy)*(a.y-oy)<(b.x-ox)*(b.x-ox)+(b.y-oy)*(b.y-oy))return 1;
	return 0;
}
ll dis(const node &a,const node &b){
	return ((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); 
} 
node s0[100005];
int n,v,k=1;
ll miny=2147483647,minx=-2147483647;
ll ans[100005];
int main(){
	scanf("%d",&n);
	for(int i=0;i<n;i++){
		scanf("%lld%lld",&s0[i].x,&s0[i].y);
	}
	for(int i=0;i<n;i++){
		if(miny>s0[i].y){
			miny=s0[i].y;
			minx=s0[i].x;
			v=i;
		}
		if(miny==s0[i].y){
			if(minx>s0[i].x){
				minx=s0[i].x;
				v=i;
			}
		}
	}
	ox=s0[v].x;oy=s0[v].y;
	ll temp,xx;
	temp=s0[0].x;s0[0].x=s0[v].x;s0[v].x=temp;
	temp=s0[0].y;s0[0].y=s0[v].y;s0[v].y=temp;
	sort(s0+1,s0+n);
	ans[0]=0;ans[1]=1;
	for(int i=2;i<n;i++){
		ox=s0[ans[k-1]].x;oy=s0[ans[k-1]].y;
		xx=(s0[ans[k]]*s0[i]);
		if(xx>0){
			k++;
			ans[k]=i;
		}
		if(xx==0){
			if(comp(s0[i],s0[ans[k-1]]));
			ans[k]=i;
		}
		if(xx<0){
			if(k>2){
				k--;
				i--;
			}
			else
			ans[k]=i;
		}
	}
	for(int i=0;i<=k;i++){
		for(int j=0;j<=k;j++){
			maxn=mx(maxn,dis(s0[ans[i]],s0[ans[j]])); 
		}
	}
	ansn=(double)(sqrt(maxn*1.0));
	printf("%.2lf",ansn); 
	return 0;
}
AC截图:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值