UVA - 10245 The Closest Pair Problem

题目链接:
UVA - 10245 The Closest Pair Problem
题意:
给定一群点,求出这群点里面最短的两个点的距离
思路:
主要思想是分冶合并
首先将这群点按先x后y的顺序排序
然后根据中点将这群点分成左右两部分,最小距离可能两个点同时在左边,两个点同时在右边,也有可能一个点在左边一个点在右边。对于一个点在左边一个点在右边这种情况,首先设前面求出的仅在两边的最小距离d,这时候从左边取出p[mid].x-p[i].x<d的点,从右边取出p[j].x-p[mid].x<d,只有这些点才可能距离小于d(根据两边之和大于第三边)
这里还可以进一步优化,那就是在这个的基础上,如果fabs(p[i].y-p[j].y)>d直接抛弃,因为此时的这两个点距离一定大于d
坑点:
建议点的坐标用double类型,不然sqrt将int转化为double会导致最后TLE
其次浮点数取绝对值用fabs(),而不是abs()

#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define MAX 0xffffffff
using namespace std;
struct Point{
	double x,y;//这里用double,减少后面求sqrt时由int转化为double的时间,不然容易TLE
}p[10010];
bool cmp1(const Point &p1,const Point &p2){
	if(p1.x==p2.x) return p1.y<p2.y;
	return p1.x<p2.x;
}
double dist(const Point &p1,const Point &p2){
	return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}
double dfs(int l,int r){
	if(l==r) return MAX;
	if(l+1==r) return dist(p[l],p[r]);
	int mid=(l+r)>>1;
	double d=min(dfs(l,mid),dfs(mid,r));
	for(int i=mid-1;i>=l&&p[mid].x-p[i].x<d;i--){
		for(int j=mid+1;j<=r&&p[j].x-p[mid].x<d;j++){
			if(fabs(p[i].y-p[j].y)>d) continue;//这里用浮点数取值fabs(),代替abs()
			d=min(d,dist(p[i],p[j]));
		}
	}
	return d;
}
int main(int argc, char** argv) {
	int n;
	while(scanf("%d",&n)!=EOF){
		if(n==0) break;
		for(int i=0;i<n;i++){
			scanf("%lf %lf",&p[i].x,&p[i].y);
		}
		sort(p,p+n,cmp1);
		
		double dis=dfs(0,n-1);
		if(dis>=10000.0) printf("INFINITY\n");
		else printf("%.4lf\n",dis);
	}
	return 0;
}

最开始的思路:
先将这群点按先x后y的顺序排序
然后根据每个点到最开始点的距离再次排序
最后计算相邻两个点的距离
(然而TLE…qwq…

#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
//#define MAX 0xffffffff
using namespace std;
struct Point{
	int x,y;
}p[10010];
bool cmp1(const Point &p1,const Point &p2){
	if(p1.x==p2.x) return p1.y<p2.y;
	return p1.x<p2.x;
}
bool cmp_dis(const Point &p1,const Point &p2){
	double dis1=sqrt(pow((p1.x-p[0].x),2)+pow((p1.y-p[0].y),2));
	double dis2=sqrt(pow((p2.x-p[0].x),2)+pow((p2.y-p[0].y),2));
	return dis1<dis2;
}
int main(int argc, char** argv) {
	int n;
	while(scanf("%d",&n)!=EOF){
		if(n==0) break;
		for(int i=0;i<n;i++){
			scanf("%d %d",&p[i].x,&p[i].y);
		}
		sort(p,p+n,cmp1);
		sort(p,p+n,cmp_dis);
		double dis=10000;
		for(int i=0;i<n-1;i++){
			double dis_tmp=sqrt(pow(p[i].x-p[i+1].x,2)+pow(p[i].y-p[i+1].y,2));
			if(dis_tmp<dis){
				dis=dis_tmp;
			}
		}
		if(dis>=10000) printf("INFINITY\n");
		else printf("%.4lf\n",dis);
	}
	return 0;
}

思路参考:
https://blog.csdn.net/zju_ziqin/article/details/22920205

猜你喜欢

转载自blog.csdn.net/zhuixun_/article/details/84439810