传输门P1429 平面最近点对(加强版) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)https://www.luogu.com.cn/problem/P1429
题目描述
给定平面上 n 个点,找出其中的一对点的距离,使得在这 n 个点的所有点对中,该距离为所有点对中最小的
输入输出样例
输入 #1
3 1 1 1 2 2 2
输出 #1
1.0000
一,暴力解法
#include<bits/stdc++.h>
using namespace std;
const int N = 1000;
struct node{
double x, y;
}a[N];
#define INF 1<<31-1
int n;
double dis(node x, node y)
{
return sqrt((x.x - y.x) * (x.x - y.x) + (x.y - y.y) * (x.y - y.y));
}
int main()
{
cin >> n;
for(int i = 1; i <= n; i++)
{
cin >> a[i].x >> a[i].y;
}
double minn = INF;
for(int i = 1; i < n; i++)
{
for(int j = i + 1; j <= n; j++)
{
minn = min(minn, dis(a[i], a[j]));
}
}
cout << minn;
}
二,分治法
1,首先我们先对各个点的x坐标进行排序
2,把各个点平分成两部分,我们求左边部分的点中的两点之间的最小距离d1,再求出右边部分的点中的两点之间的最小距离d2。比较这两个最小距离,求出最小的最小距离d。
3,我们应该考虑到另一种情况,即左边有一个点,右边有一个点,这两点之间的距离比左边右边的最小距离还要小,那么,我们如何找到这两个点呢。
首先,我遍历所以的点,如果有个点和中间点的距离 <= minn,那我们就把这个点的下标记录下来。
其次,我们对这记录下来的几个点进行遍历,寻找最小距离的两个点。这时候你可能就会有疑问了,这不还是两层循环吗,但是实际上,如果我们已经确定了一个点,那另一个点就只有六种情况。
可以看出,内层循环其实是常数级别的,时间复杂度为O(nlogn)
#include<iostream>
#include<math.h>
#include<algorithm>
#include<string.h>
using namespace std;
#define Inf 1<<31-1
const int N = 200005;
struct Point{
double x;
double y;
}P[N];
int mpt[300005];
bool cmp1(Point a,Point b)
{
if(a.x==b.x)return a.y<b.y;
return a.x<b.x;
}//第一个排序是按照x坐标排序,排序以后才好分左右平面
bool cmp2(int a,int b)
{
return P[a].y<P[b].y;
}//第二个排序是选择中间的点,不懂得往下看
double dis(Point x, Point y)
{
return sqrt((x.x - y.x) * (x.x - y.x) + (x.y - y.y) * (x.y - y.y));
}
double solve(int left, int right)
{
int maxx = Inf;
if(left == right)return maxx;
if(left + 1 == right)return dis(P[left], P[right]);
int mid = (left + right) / 2;
double d1 = solve(left, mid - 1);
double d2 = solve(mid, right);
double d = min(d1, d2);
int k = 0;
for(int i = left; i <= right; i++)
{
if(fabs(P[i].x - P[mid].x) <= d)
mpt[++k] = i;
}
sort(mpt + 1, mpt + 1 + k, cmp2);
for(int i = 1; i <= k; i++)
{
for(int j = i + 1; j <= k && P[mpt[j]].y - P[mpt[i]].y <= d; j++)
{
if(d > dis(P[mpt[i]], P[mpt[j]]))
d = dis(P[mpt[i]], P[mpt[j]]);
}
}
return d;
}
int n;
int main()
{
cin >> n;
for(int i = 1; i <= n; i++)
{
cin >> P[i].x >> P[i].y;
}
sort(P + 1, P + 1 + n, cmp1);
printf("%.4f", solve(1, n));
}
今天的分享就到这里啦!