方法一
我们充分发扬人类的智慧。
将 x 和 y 分别排序然后取 100 个,进行判断。
方法二
考虑分治将 (1,10) 分成 (1,5),(6,10) 两个问题,再不断分治。
现在我们知道了子问题的答案,考虑合并,首先这个肯定是要横跨两边的,因为不横跨的已经算过了,那么打中间的距离大于现在答案的直接 out ,不可能成为答案。
然后按 y 轴排序,进行枚举点,这个时候如果两个 y 的距离大于答案,直接 break 后面的 y 只会越来越大。
核心代码:
double dfs(int l,int r)
{
int mid;
double ans;
if(l==r) return INF;
mid=(l+r)/2;
ans=min(dfs(l,mid),dfs(mid+1,r));
int k=0;
for(int i=l;i<=r;++i)
if(abs(a[mid].x-a[i].x)<=ans) p[++k]=a[i];//可能成为答案的点集
sort(p+1,p+1+k,cmp2);
for(int i=1;i<=k;++i)
for(int j=i+1;j<=k;++j)
if(p[j].y-p[i].y<ans) ans=min(ans,sqrt((p[i].x-p[j].x)*(p[i].x-p[j].x)+(p[i].y-p[j].y)*(p[i].y-p[j].y)));
else break;//不可能成为答案,后面的也不可能
return ans;
}