分治法求平面最接近点对poj3714,洛谷P1257

poj3714
洛谷P1257
在这里插入图片描述
在这里插入图片描述
这里有一步优化,对所有横坐标 i ∈ [ l , r ] i\in[l,r] i[l,r]之间满足 ∣ a [ i ] . x − a [ m i d ] . x ∣ < d |a[i].x-a[mid].x|<d a[i].xa[mid].x<d的点,我们将y坐标从小到大排序,在之后遍历所有合格点之间的距离的时候,一旦 a [ j ] . y − a [ i ] . y > d a[j].y-a[i].y>d a[j].ya[i].y>d就可以break。

ps:一定要用scanf

#include<iostream>
#include<vector>
#include<string.h>
#include<string>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;

#define MAX 100005
#define ll long long
#define inf 10000000005

struct P {
	double x, y, k;//k:0表示station 1表示agent
	P(double a = 0, double b = 0, int kind = 0) { x = a, y = b, k = kind; }
}a[MAX * 2], t[MAX * 2];

bool cmp(P p1, P p2) {
	if (p1.x == p2.x) return p1.y < p2.y;
	else return p1.x < p2.x;
}

bool cmpy(P p1, P p2) {
	return p1.y < p2.y;
}

double dist(P p1, P p2) {
	if (p1.k == p2.k) return inf;
	return sqrt((p1.x - p2.x)*(p1.x - p2.x) + (p1.y - p2.y)*(p1.y - p2.y));
}

ll N, n;

double merge(ll l, ll r) {
	if (l == r)return inf;
	if (l == r - 1) return dist(a[l], a[r]);
	ll mid = (l + r) >> 1;
	double d1 = merge(l, mid), d2 = merge(mid + 1, r), d = min(d1, d2);
	int i, j, k = 0;
	
	for (i = l; i <= r; i++) {
		if (fabs(a[i].x - a[mid].x) < d)
			t[k++] = a[i];
	}
	sort(t, t + k, cmpy);//x都符合要求,那么我们按y坐标从小到大排序
	for (int i = 0; i < k; i++) {
		for (int j = i + 1; j < k && t[j].y - t[i].y < d; j++) {
			double dis = dist(t[i], t[j]);
			d = min(d, dis);
		}
	}
	return d;
}

int main() {
	cin >> N;
	while (N--) {
		cin >> n;
		for (int i = 0; i < 2 * n; i++) {
			scanf("%lf%lf", &a[i].x, &a[i].y);
			if (i < n)a[i].k = 0;
			else a[i].k = 1;
		}
		sort(a, a + 2 * n, cmp);//打乱排列进行排序
		printf("%.3f\n", merge(0, 2 * n - 1));
	}
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值