【蛮力法&分治法】最近点对问题

题目(Description):

设 p1=(x1, y1), p2=(x2, y2), …, pn=(xn, yn) 是平面上 n 个点构成的集合 S,设计分治法算法,找出集合 S 中距离最近的点对。严格地讲,最接近点对可能多于一对,简单起见,只找出其中的一对作为问题的解。

输入(Input):
点对个数n
点对坐标(x, y)

输出(Output):
最近对的距离(小数点后面保留6位)

示例(Sample):

输入(Input):

6
2 2
2.1 2.1
3.5 6
6 10
1.3 9.2
2 5

输出(Output):
0.141421

思路1

采用蛮力法

算法实现1

double ClosestPoints(Point S[], int n) { // 蛮力法求解 
	int i, j;
	double d, minDist = DBL_MAX;
	for(i=0; i<n; i++) {
		for(j=i+1; j<n; j++) {
			d = Distance(S[i],S[j]);
			if(d < minDist) {
				minDist = d;
			}
		}
	}
	return minDist;
}

测试1

int main()
{
	int n; //点的数量 
	cin >> n;
	Point S[N];
	for(int i=0; i<n; i++)
		cin >> S[i].x >> S[i].y;	
	cout << ClosestPoints(S,n);
	return 0;
}
6
2 2
2.1 2.1
3.5 6
6 10
1.3 9.2
2 5
0.141421
--------------------------------

思路2

采用分治法

算法实现2

double ClosestPoints(Point S[], int low, int high) { //分治法 
	double d, d1, d2, d3;
	int mid, i, j, index;
	Point P[N]; // 存放P1 P2 
	if(high-low == 1) { // 只有两个点 
		return Distance(S[low], S[high]);
	}
	if(high-low == 2) { // 只有三个点 
		d1 = Distance(S[low], S[low+1]);
		d2 = Distance(S[low+1], S[high]);
		d3 = Distance(S[low], S[high]);
		
		if((d1<d2) && (d1<d3)) 
			return  d1;
		else if (d2<d3) return d2;
		else return d3; 
	}
	mid = (low+high)/2; //计算中间点
	d1 = ClosestPoints(S,low,mid);     //递归求解子问题1 
	d2 = ClosestPoints(S,mid+1,high);  //递归求解子问题2
	
	//下面处理子问题3 
	d = d1>d2?d2:d1; //先合并子问题1和2的解 
	index=0;
	for(i=mid; (i>=low)&&(S[mid].x<S[i].x); i--) 
		P[index++] = S[i];
	for(i=mid+1; (i<=high)&&(S[mid].x)>S[i].x; i++) 
		P[index++] = S[i];
	sort(P,P+index,cmpy); //按照y升序排列 

	for(i=0; i<index; i++) {
		for(j=i+1; j<index; j++) {
			if(P[j].y-P[i].y >= d) //这些点不在矩形区域内 不需要考虑 
				break;
			else { // 可疑点 需要计算距离 并更新子问题3的解d3 
				d3 = Distance(P[i],P[j]); 
				if(d3<d) d=d3; // 合并解 
			}
		}
	}
	return d;
}

测试2

int main()
{
	int n; //点的数量 
	cin >> n;
	Point S[N];
	for(int i=0; i<n; i++)
		cin >> S[i].x >> S[i].y;
	cout << ClosestPoints(S,0,n);
	return 0;
}
6
2 2
2.1 2.1
3.5 6
6 10
1.3 9.2
2 5
0.141421
--------------------------------

注:前缀代码

#include <iostream>
#include <cmath>
#include <float.h>
#include <algorithm>
using namespace std;
#define N 10

typedef struct point {
	double x, y;
}Point;
bool cmpx(Point a, Point b) {
	return a.x < b.x;
}
bool cmpy(Point a, Point b) {
	return a.y < b.y;
}
double Distance(Point a, Point b) {
	return sqrt( (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
}
  • 7
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值