题面:

解题:
爆力枚举?
首先,判断一下Brute Force能否解决问题?
对于每个新出现的点d[i],都有与d[0]~d[i-1]间产生答案最短距离的可能性,
已知暴力枚举的时间复杂度为O(n²),对于数据范围n≤10000来说,这样的算法很难受得住考研。
分治+递归
如下图,我们假设二维空间上有0~6共7个点,先将这7个点按x坐标一分为二(橙线),
取0~(0+6)/2 为左半,即点:0 1 2 3 则 4 5 6为右半
再重复上述过程,用蓝线分割,使得每个区间含的点数量不多余2个。
于是,对于含2个点的小区间里,我们求出了两点间距;对于含1个点的区间不操作。

现在,只看橙线左半部分,将0、1区间距离标记d1,2、3区间距离标记为d2,
d1 、d2作为值返回给外层的循环,即包含点0、1、2、3的循环。
接收到d1、d2的值后,进行比对,得出d=min(d1,d2)=d2,
但,蓝线区间内的最短点组,也可能是由一个左区间的点,一个右区间的点组成的。
为解决此问题,我们选取分割点mid=(0+3)/2=1 点为搜索轴,
搜索右侧与mid点横、纵坐标差均不超过d的点,
即:绿色矩形范围内的点,将这些点全部加入temp;
同样,我们也要搜索左侧与mid点的横、纵坐标差均不超过d的点,加入temp……
构造完temp,再枚举temp中各两点间的元素的距离,
比d距离还要小两个点只可能在temp内的两点之间产生。
如此,我们得出一套分治+递归算法:通过小区间内产生的d,来缩小更大的区间需要搜索的范围,从而实现减少重复搜索的目的。

AC代码奉上
#include<iostream>
#include<algorithm>
#include<vector>
#include<cmath>
using namespace std;
class Dot
{
public:
double x; //坐标
double y;
};
int n;
double ans = 9999999999;
vector<Dot>v; //储存点
int temp[10005]; //临时数组,存放临时点的索引
class MyCompare
{
public:
bool operator ()(Dot &d1,Dot &d2) const
{
return d1.x < d2.x;
}
};
bool cmp(const int &i,const int &j) //纵坐标降序排序
{
return v[i].y < v[j].y;
}
double dis(int i, int j) //获取距离
{
return sqrt(fabs((v[i].x - v[j].x) * (v[i].x - v[j].x) + (v[i].y - v[j].y) * (v[i].y - v[j].y)));
}
double getMinDis(int left, int right) //返回该区间内点的最小距离
{
double ret = 10 << 15; //初始化为无穷大
if (left == right)return ret;
else if (left + 1 == right) { return dis(left, right); }
int mid = (left + right) >> 1; //中值=(left+right)/2
double dl = getMinDis(left, mid); //左区间的最短长度
double dr = getMinDis(mid + 1, right); //右区间的最短长度
double d = min(dl, dr);//左、右区间最短长度中较短者,将搜索范围缩小至mid-d,mid+d
cout << "d=" << d << endl;
int k = 0; //temp的容量
for (int i = left; i <= right; i++)
if (fabs(v[i].x - v[mid].x) <= d) //存入temp:在mid-d,mid+d的区间内
temp[k++] = i;
sort(temp, temp + k, cmp); //按y排序
for (int i = 0; i < k; i++)
for (int j = i + 1; j < k && v[temp[j]].y - v[temp[i]].y <= d; j++)
d = min(d, dis(temp[i], temp[j]));
return d;
}
int main()
{
cin >> n;
if (n == 1) { cout << "0.0000" << endl; return 0; } //特判n=1
for(int i=1;i<=n;i++)
{
Dot d;
cin>>d.x>>d.y;
v.push_back(d);
}
sort(v.begin(), v.end(), MyCompare());//按x排序
ans = getMinDis(0, n - 1); //0~n-1,即vector容器的全部元素
printf("%.4lf", ans);
return 0;
}