hdoj1007(最近距离点对)Quoit Design

通过分治策略解决HDOJ1007题,先按x坐标排序,然后递归处理左右区间找到最小区间。再依据中线筛选符合条件的点,最后按y坐标排序并检查所有点对,复杂度为O(nlogn)。

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

<pre class="cpp" name="code"><strong><span style="font-size:18px;">这题直接暴力会tle,正确解法是分治:先按x坐标排序分左右两个区间,求出这两个区间内的最小距离,然后处理两个点在中线左右两边的情况,这时候只考虑分布在中线两侧距离在d之内的点,同时这些点的y方向距离也应在d之内,这样总的复杂度就能够控制在O(nlogn),具体在区间内的点的个数上限好像是7,不过推导过程比较麻烦没太看懂,总之在处理中间得点时需要处理的数量是O(n)的</span></strong>
#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cmath>
#define REP(n) for(int R=0;R<(n);R++)
typedef long long i64;
#define MX 100005
using namespace std;
typedef pair<double,double> P;////(x,y)
P A[MX];
int N;
bool cmp_y(P a,P b){
	return a.second<b.second;///按照y排序的比较函数
}
double closest_pair(P *a,int sz){///进入函数时是按照x排序的
	if(sz<=1)
		return 1e100;
	int m=sz/2;
	double midx=a[m].first;///中间值
	double d=min(closest_pair(a,m),closest_pair(a+m,sz-m));///递归处理左右区间的最小d
	inplace_merge(a,a+m,a+sz,cmp_y);///此时(递归处理后)左右两区间已经按y排好序了,
	///使用stl的归并排序,复杂度O(n)
	vector<P> B;
	for(int i=0;i<sz;i++){
		if(abs(a[i].first-midx)<d){///x方向距离限制
			for(int j=B.size()-1;j>=0;j--){
				double dx=B[j].first-a[i].first,dy=B[j].second-a[i].second;
				if(abs(dy)>=d)///从后往前检查y方向距离是否小于d
					break;
				d=min(d,sqrt(dx*dx+dy*dy));
			}
			B.push_back(a[i]);
		}
	}
	return d;
}
int main(){
    while(cin>>N,N){
		REP(N)scanf("%lf%lf",&A[R].first,&A[R].second);
		sort(A,A+N);
		printf("%.2lf\n",closest_pair(A,N)/2);
	}
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值