UVA 10245 The Closest Pair Problem 最近点问题 分治算法

题意,给出n个点的坐标,找出两点间最近的距离,如果小于10000就输出INFINITY。

纯暴力是会超时的,所以得另辟蹊径,用分治算法。

递归思路将点按坐标排序后,分成两块处理,最近的距离不是在两块中的一块中,就会存在于跨越中线的点对中。

查找跨越中线的点比较麻烦,之前已经求出两块中的最小距离,只要在x范围在[m-d,m+d]的点中找对,更新最小距离,最后返回最小距离即可。

代码:

 

 /*

 *   Author:        illuz <iilluzen[at]gmail.com>

 *   Blog:          http://blog.csdn.net/hcbbt

 *   File:          uva10245.cpp

 *   Lauguage:      C/C++

 *   Create Date:   2013-09-04 19:57:26

 *   Descripton:    UVA 10245 The Closest Pair Problem, partitation

 */

#include <cstdio>

#include <cstdlib>

#include <cmath>

#include <algorithm>

using namespace std;

#define rep(i, n) for (int i = 0; i < (n); i++)

#define sqr(x) ((x) * (x))

#define dis(i, j) (sqrt(sqr(p[i].x - p[j].x) + sqr(p[i].y - p[j].y)))



const int MAXN = 10010;

struct Point {

	double x;

	double y;

} p[MAXN];

int n, t[MAXN];

double Min;



bool cmp1(Point a, Point b) {

	return a.x < b.x;

}



bool cmp2(int a, int b) {

	return p[a].y < p[b].y;

}



double solve(int l, int r) {

	if (l == r) return 0xfffffff;

	if (l + 1 == r) return dis(l, r);

	int mid = (l + r) / 2;

	double d = min(solve(l, mid), solve(mid + 1, r));

	int c = 0;

	for (int i = l; i <= r; i++)

		if (fabs(p[mid].x - p[i].x) <= d)

			t[c++] = i;

	sort(t, t + c, cmp2);

	for (int i = 0; i < c; i++)

		for (int j = i + 1; j < c && p[t[j]].y - p[t[i]].y < d; j++) {

			double td = dis(t[i], t[j]);

			if (d - td > 1e-9) d = td;

		}

	return d;

}



int main() {

	while (scanf("%d", &n) && n) {

		rep(i, n) scanf("%lf%lf", &p[i].x, &p[i].y);

		sort(p, p + n, cmp1);

		Min = solve(0, n - 1);

		if (Min - 10000 <= 1e-9) printf("%.4lf\n", Min);

		else printf("INFINITY\n");

	}

	return 0;

}


 

 

你可能感兴趣的:(close)