【模拟试题】最远距离点对

【模拟试题】最远距离点对

Description

  给定平面上的n个点,找出它们之间最远的点对。

Input

  多组数据,每组第一行n代表点数,接着n行为点的坐标,坐标为整数,不超过10^18范围。n<=30000。

Output

  每组一行,最远点对的距离,保留2位小数

Sample Input

4

0 0

1 1

0 1

1 0

Sample Output

1.41

Source

找出凸包,旋转卡壳。

注意方向。。。

CODE

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
struct Point {long long x,y;}p[30005];
inline bool cmp(Point A,Point B){return A.y<B.y||A.y==B.y&&A.x<B.x;}
int S[30005],q[30005];
inline long long read(){
	char c;int rec=0,f=1;
	while((c=getchar())<'0'||c>'9')if(c=='-')f=-1;
	while(c>='0'&&c<='9')rec=rec*10+c-'0',c=getchar();
	return rec*f;
}
int n;
inline long long Cross(Point A,Point B,Point X){
	return (A.x-X.x)*(B.y-X.y)-(B.x-X.x)*(A.y-X.y);
}
inline long long Cal(Point A,Point B){
	return (A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y);
}
void Scan(){
	int i,j,top=2;
	q[1]=1;q[2]=2;
	for(i=3;i<=n;i++){
		while(top>1&&Cross(p[q[top]],p[i],p[q[top-1]])<=0)top--;
		q[++top]=i;
	}
	for(i=1;i<=top;i++)S[i]=q[i];S[0]=top;
	q[1]=n;q[2]=n-1;top=2;
	for(i=n-2;i>=1;i--){
		while(top>1&&Cross(p[q[top]],p[i],p[q[top-1]])<=0)top--;
		q[++top]=i;
	}i=1;
	if(q[1]==S[S[0]])i=2;
	for(;i<=top;i++)S[++S[0]]=q[i];
	return ;
}
void Farest(){
	int i,j=1;
	long long ans=0;
	S[n+1]=S[1];
	for(i=1;i<=S[0];i++){
		while(Cross(p[S[i+1]],p[S[j+1]],p[S[i]])>Cross(p[S[i+1]],p[S[j]],p[S[i]]))j=(j+1)%S[0];
		ans=max(ans,max(Cal(p[S[i+1]],p[S[j+1]]),Cal(p[S[i]],p[S[j]])));
	}
	printf("%.2lf",sqrt(double(ans)));
	return ;
}
int main(){
	n=read();
	int i,x,y;
	for(i=1;i<=n;i++){p[i].x=read();p[i].y=read();}
	sort(p+1,p+1+n,cmp);
	Scan();
	Farest();
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值