#include <iostream>
#include <string>
#include <cstring>
#include <cstdio>
#include <cmath>
#define inf d[0][0]
using namespace std;
int n, x[200], y[200];
double d[200][200];
double dis(int i, int j) {
return sqrt((x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]));
}
int fa[200];
int get(int x) {
if (fa[x] == x) return x;
return fa[x] = get(fa[x]);
}
void connect(int x, int y) {
int fa_x = get(x);
int fa_y = get(y);
if (fa_x != fa_y) {
fa[x] = y;
}
}
void init() {
cin >> n;
memset(d, 127, sizeof(d));
for (int i = 1; i <= n; i++) {
cin >> x[i] >> y[i];
fa[i] = i;
}
for (int i = 1; i <= n; i++) {
string s;
cin >> s;
for (int j = 1; j <= n; j++) {
if (s[j - 1] == '0') {
d[i][j] = inf;
} else {
d[j][i] = dis(i, j);
connect(i, j);
}
}
d[i][i] = 0;
}
}
void Floyd() {
for (int k = 1; k <= n; k++) {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (get(i) == get(j) && get(i) == get(k)) {
if (d[i][k] != inf && d[k][j] != inf) {
d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
}
}
}
}
}
}
double MAX[200];
void find_max() {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (get(i) == get(j) && d[i][j] != inf) {
MAX[i] = max(MAX[i], d[i][j]);
}
}
}
}
double search() {
double ans = inf;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (get(i) != get(j)) {
ans = min(ans, MAX[i] + MAX[j] + dis(i, j));
}
}
}
for (int i = 1; i <= n; i++) {
ans = max(ans, MAX[i]);
}
return ans;
}
int main() {
init();
Floyd();
find_max();
printf("%.6f", search());
return 0;
}