#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
using namespace std;

typedef complex<double> point; // 2D point only
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldob;
typedef pair<int, int> ii;
typedef pair<int, ii> iii;
typedef pair<ii, int> ii_i;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<ii> vii;
typedef vector<iii> viii;

#define re real()
#define im imag()
#define fi first
#define se second

// OST
template <typename T>
using ordered_set = __gnu_pbds::tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

// from: https://codeforces.com/blog/entry/62393
struct custom_hash {
	static uint64_t splitmix64(uint64_t x) {
		// http://xorshift.di.unimi.it/splitmix64.c
		x += 0x9e3779b97f4a7c15;
		x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
		x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
		return x ^ (x >> 31);
	}

	size_t operator()(uint64_t x) const {
		static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
		return splitmix64(x + FIXED_RANDOM);
	}
};

const int INF = ~(1<<31);
const ll LINF = (1LL << 60);
const long double EPS = 1e-9;
const long double PI = acos(-1);

const int N = 100001;
const int NN = 1001;
const int MOD = 1e9+9;
const int IMAX = 1e9+7;
const int dx[4] = {0,0,-1,1};
const int dy[4] = {-1,1,0,0};

template <typename T>
struct vector2D {
	T x, y;
	vector2D<T>(T _x = 0, T _y = 0): x(_x), y(_y) {}
	vector2D<T> operator+(const vector2D& rhs) const {
		return vector2D<T>(x+rhs.x,y+rhs.y);
	}
	vector2D<T> operator-(const vector2D& rhs) const {
		return vector2D<T>(x-rhs.x,y-rhs.y);
	}
	vector2D<T> operator*(const T& r) const {
		return vector2D<T>(x*r,y*r);
	}
	vector2D<T> operator/(const T& r) const {
		return vector2D<T>(x/r,y/r);
	}
	T operator*(const vector2D<T>& rhs) const {
		return x*rhs.x+y*rhs.y;
	}
	T operator%(const vector2D<T>& rhs) const {
		return x*rhs.y-rhs.x*y;
	}
	bool operator==(const vector2D<T>& rhs) const {
		return (x == rhs.x) and (y == rhs.y);
	}
	bool operator!=(const vector2D<T>& rhs) const {
		return (x != rhs.x) or (y != rhs.y);
	}
	bool operator<(const vector2D<T>& rhs) const {
		if (x != rhs.x) return x < rhs.x;
		return y < rhs.y;
	}
	vector2D<T> perp() {
		return vector2D<T>(y,-x);
	}
};

template <typename T>
istream& operator>>(istream& i, vector2D<T>& v) {
	i >> v.x >> v.y;
	return i;
}

template <typename T>
ostream& operator<<(ostream& o, const vector2D<T>& v) {
	o << v.x << ' ' << v.y;
	return o;
}

int n;
vector<vector2D<double>> pts(51);

double dist (vector2D<double> a, vector2D<double> b) {
	return sqrt((b-a)*(b-a));
}

double getr (double x, double y) {
	vector2D<double> O(x,y);
	double ans = 0;
	for (int i = 0; i < n; ++i) {
		ans = max(ans, dist(pts[i],O));
	}
	return ans;
}

double tsy (double x) {
	double l = 0, r = 1001;
	for (int i = 0; i < 300; ++i) {
		double mid1 = l + (r-l)/3.0;
		double mid2 = r - (r-l)/3.0;
		if (getr(x,mid1) > getr(x,mid2)) {
			l = mid1;
		} else {
			r = mid2;
		}
	}
	return getr(x,l);
}

double tsx () {
	double l = 0, r = 1001;
	for (int i = 0; i < 300; ++i) {
		double mid1 = l + (r-l)/3.0;
		double mid2 = r - (r-l)/3.0;
		if (tsy(mid1) > tsy(mid2)) {
			l = mid1;
		} else {
			r = mid2;
		}
	}
	return tsy(l);
}

int main () {
	ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	cout.precision(10); cout << fixed;

	cin >> n;
	for (int i = 0; i < n; ++i)
		cin >> pts[i];

	if (n == 1) {
		cout << 0.0 << endl;
		return 0;
	} else if (n == 2) {
		cout << dist(pts[0],pts[1])/2.0 << endl;
		return 0;
	}

	cout << tsx() << endl;

	return 0;
}

Measured memory_bytes: 3828