#include <bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define rep(i,x,n) for(register int i=x;i<n;i++)
#define repd(i,x,n) for(register int i=x;i<=n;i++)
#define MAX 1000005
#define MOD 1000000007
#define FI first
#define SE second
#define MP make_pair
#define PB push_back
#define PII pair<int,int>
template<class T>inline void rd(T &x) {
x = 0;
char o, f = 1;
while (o = getchar(), o < 48)
if (o == 45)
f = -f;
do
x = (x << 3) + (x << 1) + (o ^ 48);
while (o = getchar(), o > 47);
x *= f;
}
template<class T>inline void print(T x, bool op = 1) {
static int top, stk[105];
if (x < 0)
x = -x, putchar('-');
if (x == 0)
putchar('0');
while (x)
stk[++top] = x % 10, x /= 10;
while (top)
putchar(stk[top--] + '0');
putchar(op ? '\n' : ' ');
}
using namespace std;
const int N = 200;
const double INF = 2e16;
int n, m, k;
double dis[N][N];
int g[N][N];
struct node {
double x, y;
} ns[N];
int f[N];
int inline find(int x) {
if (f[x] == x)
return x;
return f[x] = find(f[x]);
}
double cal(node a, node b) {
return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
void floyed() {
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
for (int k = 1; k <= n; k++)
dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
}
map<int, int > id;
int cnt = 0, bel[N];
vector<int > blo[N];
void dsu() {
for (int i = 1; i <= n; i++)
for (int j = i + 1; j <= n; j++)
if (g[i][j]) {
int fx = find(i), fy = find(j);
f[fx] = fy;
}
for (int i = 1; i <= n; i++) {
int fx = find(f[i]);
if (!id[fx])
id[fx] = ++cnt;
blo[id[fx]].PB(i);
bel[i] = id[fx];
}
}
double ans_blo[N], ans_dot[N];
void dot_mx() {
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
if (dis[i][j] != INF)
ans_dot[i] = max(ans_dot[i], dis[i][j]);
}
double final_ans = 2e16;
void blo_mx() {
for (int i = 1; i <= cnt; i++) {
for (int j = 0; j < blo[i].size(); j++) {
ans_blo[i] = max(ans_blo[i], ans_dot[blo[i][j]]);
}
}
}
void two_links() {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (dis[i][j] == INF)
final_ans = min(final_ans, max(
{ans_blo[bel[i]], ans_blo[bel[j]], ans_dot[i] + ans_dot[j] + cal(ns[i], ns[j])} ));
}
}
}
void solve() {
cin >> n;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
dis[i][j] = INF;
for (int i = 1; i <= n; i++)
dis[i][i] = 0;
for (int i = 1; i <= n; i++)
cin >> ns[i].x >> ns[i].y;
for (int i = 1; i <= n; i++) {
string s;
cin >> s;
for (int j = 0; j < s.length(); j++) {
g[i][j + 1] = s[j] - '0';
if (g[i][j + 1])
dis[i][j + 1] = dis[j + 1][i] = cal(ns[i], ns[j + 1]);
}
}
floyed();
dsu();
dot_mx();
blo_mx() ;
two_links();
cout << fixed << setprecision(6) << final_ans;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
solve();
return 0;
}