poj 2187 最远点对

poj 2187 最远点对
题意:
给出n个点,求最远点对的距离。

限制:
2 <= n <= 5*1e4

思路:
凸包,旋转卡壳

/*poj 2187
  题意:
  给出n个点,求最远点对的距离。
  限制:
  2 <= n <= 5*1e4
  思路:
  凸包,旋转卡壳
 */
#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std;
const double EPS=1e-10;
struct Point{
	double x,y;
	Point(){}
	Point(double _x,double _y){ x=_x; y=_y; }
	Point operator + (Point p){ return Point(x+p.x,y+p.y); }
	Point operator - (Point p){ return Point(x-p.x,y-p.y); }
	Point operator * (double d){ return Point(d*x,d*y); }
	double dot(Point p){ return x*p.x+y*p.y; }	//内积
	double det(Point p){ return x*p.y-p.x*y; }
};
bool cmpxy(const Point &p,const Point &q){
	if(p.x!=q.x) return p.x<q.x;
	return p.y<q.y;
}
vector<Point> convex_hull(Point *ps,int n){	//凸包要注意退化成2个点,1个点的情况
	sort(ps,ps+n,cmpxy);
	int k=0;
	vector<Point> qs(n*2);	//构造中的凸包
	for(int i=0;i<n;++i){	//构造凸包的下侧
		while(k>1 && (qs[k-1]-qs[k-2]).det(ps[i]-qs[k-1])<=0) --k;
		qs[k++]=ps[i];
	}
	for(int i=n-2,t=k;i>=0;--i){	//构造凸包的上侧
		while(k>t && (qs[k-1]-qs[k-2]).det(ps[i]-qs[k-1])<=0) --k;
		qs[k++]=ps[i];
	}
	qs.resize(k-1);
	return qs;
}
double dist(Point p,Point q){
	return (p-q).dot(p-q);
}
const int N=1e5+5;
Point ps[N];
void xzqk(int n){
	vector<Point> qs=convex_hull(ps,n);
	n=qs.size();
	if(n==2){	//特别处理凸包退化的情况
		printf("%.0f\n",dist(qs[0],qs[1]));
		return ;
	}
	int i=0,j=0;
	for(int k=0;k<n;++k){
		if(!cmpxy(qs[i],qs[k])) i=k;
		if(cmpxy(qs[j],qs[k])) j=k;
	}
	double ans=0;
	int si=i,sj=j;
	while(i!=sj || j!=si){
		ans=max(ans,dist(qs[i],qs[j]));
		if((qs[(i+1)%n]-qs[i]).det(qs[(j+1)%n]-qs[j])<0)
			i=(i+1)%n;
		else
			j=(j+1)%n;
	}
	printf("%.3f\n",sqrt(ans));
}
int main(){
	int T;
	int n;
	scanf("%d",&T);
	while(T--){
		scanf("%d",&n);
		for(int i=0;i<n;++i)
			scanf("%lf%lf",&ps[i].x,&ps[i].y);
		xzqk(n);
	}
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值