[AIZU ONLINE JUDGE] 计算几何 CGL_5_A (最近点对)

Closest Pair

For given n points in metric space, find the distance of the closest points.

Input

n
x0 y0
x1 y1
:
xn−1 yn−1

The first integer n is the number of points.

In the following n lines, the coordinate of the i-th point is given by two real numbers xi and yi. Each value is a real number with at most 6 digits after the decimal point.

Output

Print the distance in a line. The output values should be in a decimal fraction with an error less than 0.000001.

Constraints

  • 2 ≤ n ≤ 100,000
  • -100 ≤ xy ≤ 100

Sample Input 1

2
0.0 0.0
1.0 0.0

Sample Output 1

1.000000

Sample Input 2

3
0.0 0.0
2.0 0.0
1.0 1.0

Sample Output 2

1.41421356237

题意:

在平面中给定n个点对,要求找到这n个点对中的最小距离并输出。

代码:

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>

using namespace std;

const int N = 2e5 + 10, INF = 0x3f3f3f3f;
const double eps = 1e-10;

typedef long long LL;

int dcmp(double x, double y)
{
	if (fabs(x - y) <= eps) return 0;
	if (x > y) return 1;
	return -1;
}

struct Point
{
	double x, y;

	Point(double x = 0, double y = 0) : x(x), y(y) { }

}p[N];

int n;

bool cmpx(Point A, Point B)
{
	if (dcmp(A.x, B.x) == 0) return A.y < B.y;
	return A.x < B.x;
}
bool cmpy(Point A, Point B)
{
	return A.y < B.y;
}
double get_dist2(Point A, Point B)
{
	double dx = A.x - B.x, dy = A.y - B.y;
	return dx * dx + dy * dy;
}

double merge(Point p[], int l, int r)
{
	double d = INF;
	if (l == r) return d;
	if (l + 1 == r) return get_dist2(p[l], p[r]);

	int mid = l + r >> 1;
	d = min(merge(p, l, mid), merge(p, mid + 1, r));

	int cnt = 0;
	vector<Point> tmp(r - l + 3);
	for (int i = l; i <= r; i++)
		if ((p[mid].x - p[i].x) * (p[mid].x - p[i].x) <= d)
			tmp[++cnt] = p[i];

	sort(tmp.begin() + 1, tmp.begin() + cnt + 1, cmpy);

	for(int i = 1; i <= cnt; i ++)
		for (int j = i + 1; j <= cnt; j++)
		{
			if ((tmp[j].y - tmp[i].y) * (tmp[j].y - tmp[i].y) > d) break;
			d = min(d, get_dist2(tmp[i], tmp[j]));
		}

	return d;
}

int main()
{
	cin >> n;
	for (int i = 1; i <= n; i++) cin >> p[i].x >> p[i].y;

	sort(p + 1, p + 1 + n, cmpx);
	double ans = merge(p, 1, n);

	printf("%.11lf\n", sqrt(ans));

	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值