#include <stdio.h>
#include <math.h>
#include <stdlib.h>
typedef struct {
int x, y, val;
} punct;
double calc_dist(int p1, int p2, punct *coord) {
return sqrt(pow(coord[p1].x - coord[p2].x, 2) +
pow(coord[p1].y - coord[p2].y, 2));
}
double calc_dist_min(int L, int R, int *sort_y, punct *coord);
int comparator(const void *a, const void *b);
int main() {
int n;
int *sort_y;
punct *coord;
double dist_min;
FILE *fin = fopen("cmap.in", "r");
FILE *fout = fopen("cmap.out", "w");
fscanf(fin, "%d", &n);
coord = malloc((n+1) * sizeof *coord);
sort_y = malloc((n+1) * sizeof *sort_y);
for (int i = 1; i <= n; i++) {
fscanf(fin, "%d %d", &(coord+i)->x, &(coord+i)->y);
coord[i].val = i;
}
qsort(coord+1, n+1, sizeof *coord, comparator);
for (int i = 0; i <= n; i++) {
sort_y[i] = i;
}
dist_min = calc_dist_min(1, n+1, sort_y, coord);
fprintf(fout, "%.6f", dist_min);
free(coord);
return 0;
}
int comparator(const void *a, const void *b) {
punct *p1 = (punct *)a;
punct *p2 = (punct *)b;
if (p1->x == p2->x) {
if (p1->y == p2->y) return 0;
else if (p1->y > p2->y) return 1;
return -1;
}
else if (p1->x > p2->x) return 1;
return -1;
}
double min_interval(int L, int R, int *sort_y, punct*coord) {
double d_min = calc_dist(sort_y[L], sort_y[L+1], coord);
double d_temp;
// incerc toate posibilitatile
for (int i = L; i < R; i++) {
for (int j = L; j < i; j++) {
d_temp = calc_dist(sort_y[i], sort_y[j], coord);
if (d_temp < d_min) d_min = d_temp; // trebuie sa initializez d_min;
}
}
return d_min;
}
double calc_dist_min(int L, int R, int *sort_y, punct *coord) {
double d_min;
if (R-L < 4) {
// insertion sort dupa coordonata y
for (int i = L+1; i < R; i++) {
int t_y = sort_y[i];
int j = i;
while (j > L && coord[t_y].y < coord[sort_y[j-1]].y) {
sort_y[j] = sort_y[j-1];
j--;
}
sort_y[j] = t_y;
}
d_min = min_interval(L, R, sort_y, coord);
return d_min;
}
// INTERVAL MARE
int M = (L+R-1)/2;
double dL = calc_dist_min(L, M+1, sort_y, coord);
double dR = calc_dist_min(M+1, R, sort_y, coord);
d_min = dR;
if (dL < dR) d_min = dL;
double lim = d_min;
int *temp_arr = malloc((R-L) * sizeof *temp_arr);
int left = L;
int right = M+1;
int i = 0;
while (left < M+1 && right < R) {
int lp = sort_y[left];
int rp = sort_y[right];
if (coord[lp].y < coord[rp].y) {
temp_arr[i] = lp;
left++;
}
else {
temp_arr[i] = rp;
right++;
}
i++;
}
// adaug restul
while (right < R) {
temp_arr[i] = sort_y[right];
right++;
i++;
}
while (left < M+1) {
temp_arr[i] = sort_y[left];
left++;
i++;
}
int *puncte = malloc((R-L) * sizeof *puncte);
// am punctele sortate dupa y, le iau pe cele de care am nevioe
i = 0;
for (right = 1; right < R-L; right++) {
if (coord[temp_arr[right]].x >= coord[M].x - lim &&
coord[temp_arr[right]].x <= coord[M].x + lim) {
puncte[i] = temp_arr[right];
i++;
}
}
left = 0;
for (right = 1; right < i; right++) {
while (coord[puncte[left]].y < coord[puncte[right]].y - lim) {
left++;
}
for (int it = left; it < right; it++) {
double temp_dist = calc_dist(puncte[it], puncte[right], coord);
if (temp_dist < d_min) d_min = temp_dist;
}
}
// copiez din temp arr
for (int it = 0; it < R-L; it++) {
sort_y[L+it] = temp_arr[it];
}
free(temp_arr);
free(puncte);
return d_min;
}