#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
#define rint register int
#define ll long long
using namespace std;
template<typename xxx>inline void read(xxx &x)
{
x=0;int f=1;char c=getchar();
for(;c<'0'||c>'9';c=getchar()) if(c=='-') f=-1;
for(;'0'<=c&&c<='9';c=getchar()) x=(x<<1)+(x<<3)+(c^48);
x*=f;
}
template<typename xxx>inline void print(xxx x)
{
if(x<0){putchar('-');x=-x;}
if(x>=10) print(x/10);
putchar(x%10+48);
}
const int maxn=2000010;
const int inf=2e9;
int n,ans[maxn];
struct node{
double x,y;
}e[maxn];
inline bool cmp1(node a,node b)
{
if(a.x==b.x) return a.y<b.y;
else return a.x<b.x;
}
inline bool cmp2(int a,int b)
{
return e[a].y<e[b].y;
}
inline double calc(int a,int b)
{
return sqrt((e[a].x-e[b].x)*(e[a].x-e[b].x)+(e[a].y-e[b].y)*(e[a].y-e[b].y));
}
inline double merge(int l,int r)
{
double d=9999999999.0;int k=0;
if(l==r) return d;
if(l+1==r) return calc(l,r);
int mid=(l+r)>>1;
double d1=merge(l,mid);
double d2=merge(mid+1,r);
d=min(d1,d2);
for(rint i=l;i<=r;++i) if(fabs(e[mid].x-e[i].x)<=d) ans[++k]=i;
stable_sort(ans+1,ans+k+1,cmp2);
for(rint i=1;i<=k;++i)
{
for(rint j=i+1;j<=k && e[ans[j]].y-e[ans[i]].y<d;++j)
{
double dis=calc(ans[i],ans[j]);
if(dis<d) d=dis;
}
}
return d;
}
int main()
{
read(n);
for(rint i=1;i<=n;++i) scanf("%lf%lf",&e[i].x,&e[i].y);
stable_sort(e+1,e+n+1,cmp1);
printf("%.4lf",merge(1,n));
}
/*神仙算法
我们充分发扬人类智慧:
将所有点全部绕原点旋转同一个角度,然后按xx坐标排序
根据数学直觉,在随机旋转后,答案中的两个点在数组中肯定不会离得太远
所以我们只取每个点向后的5个点来计算答案
这样速度快得飞起,在n=1000000n=1000000时都可以在1s内卡过
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<ctime>
#define INF 9999999999.0
using namespace std;
struct node{
double x,y;
}a[2000010];
int n;
double ans=INF; //初始化答案为一个很大的数
bool cmp(node a,node b){
return a.x<b.x; //按照横坐标排序
}
double len(node a,node b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));//计算两点之间距离
}
void calc(){
for (int i=1;i<=n;i++){
for (int j=i+1;j<=i+5;j++){
double temp;
temp=len(a[i],a[j]);
ans=min(ans,temp);
}
}
}
void around(int ds){
for (int i=1;i<=n;i++){
double x=a[i].x,y=a[i].y;//旋转前的点
double xn,yn; //旋转后的点
double xyu=0.0,yyu=0.0; //原点
xn= (x - xyu)*cos(ds) - (y - yyu)*sin(ds) + xyu ;
yn= (x - xyu)*sin(ds) + (y - yyu)*cos(ds) + yyu ;
a[i].x=xn;
a[i].y=yn;
}
sort(a+1,a+1+n,cmp); //顺便排序
calc(); //顺便计算
}
int main(){
srand(time(NULL)); //随机数种子
for (int i=1;i<=200009;i++){
a[i].x=INF;a[i].y=INF; //初始化
}
scanf("%d",&n);
for (int i=1;i<=n;i++){
scanf("%lf%lf",&a[i].x,&a[i].y);
}
around(0); //将原图像进行排序并枚举每个点与其后五个点比较
around(rand()%360); //将图像随机(0°~359°)旋转 并排序 并计算
around(rand()%360); //将图像随机(0°~359°)旋转 并排序 并计算
printf("%.4lf",ans);
return 0;
}
*/