AcWing 119. 袭击 分治
参考博客:https://www.acwing.com/solution/AcWing/content/826/
//#include<bits/stdc++.h>
#include<map>
#include<cmath>
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N = 100100;
const int INF=1e7;
struct node
{
double x,y;
int f;
}a[N<<1],t[N<<1];
int n,m;
int cmp(node a,node b)
{
if(a.x==b.x)
return a.y<b.y;
return a.x<b.x;
}
int cmp2(node a,node b)
{
if(a.y==b.y)
return a.x<b.x;
return a.y<b.y;
}
double dist(node a,node b)
{
if(a.f==b.f)
return INF;
double dx=(a.x-b.x),dy=(a.y-b.y);
return sqrt(dx*dx+dy*dy);
}
double solve(int l,int r)
{
//先把坐标按x排序
//然后取终点
//左边答案是ans1,右边答案是ans2
//那么答案就是,
//min(ans1,ans2,两边交叉)
//对于两边,直接递归
int mid=(l+r)>>1;
if (r-l==0)
return INF;
if (r-l==1)
return dist(a[l],a[r]);
double ans=min(solve(l,mid),solve(mid+1,r));
//交叉部分
int cnt=0;
for (int i=l;i<=r;i++)
if (a[i].x>=a[mid].x-ans && a[i].x<=a[mid].x+ans)
t[++cnt]=a[i];
sort(t+1,t+1+cnt,cmp2);
for (int i=1;i<=cnt;i++)
for (int j=i+1;j<=cnt;j++)
{
if(t[j].y>=t[i].y+ans)
break;
ans=min(ans,dist(t[i],t[j]));
}
return ans;
}
int main()
{
int t;
cin>>t;
while(t--)
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i].x>>a[i].y;
a[i].f=0;
}
for(int i=n+1;i<= n<<1;i++)
{
cin>>a[i].x>>a[i].y;
a[i].f=1;
}
n<<=1;
sort(a+1,a+1+n,cmp);
printf("%0.3lf\n",solve(1,n));
}
}