#include<bits/stdc++.h>
using namespace std;
const int N = 1e3+5;
const int INF = 1e9;
int p[N], x[N], y[N];
double distances[N], dis[N], maxdis[N];
double g[N][N];
char c[N][N];
int vis[N];
int n;
double f(int x1, int y1, int x2, int y2)
{
return sqrt( 1.0 * (x1 - x2) * (x1 - x2) + 1.0 * (y1 - y2) * (y1 - y2) );
}
void floyd()
{
for(int k = 1; k <= n; k++){
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
if(i != j && i != k && j != k && g[i][k] != INF && g[k][j] != INF)
if(g[i][j] > g[i][k] + g[k][j]) g[i][j] = g[i][k] + g[k][j];
}
}
}
}
int main()
{
scanf("%d", &n);
for(int i = 1; i <= n; i++){
scanf("%d%d", &x[i], &y[i]);
}
getchar();
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
g[i][j] = INF;
}
}
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
scanf("%c", &c[i][j]);
if(c[i][j] == '1' ) {
g[i][j] = f(x[i], y[i], x[j], y[j]);
}
if(i == j) g[i][j] = 0;
}
getchar();
}
floyd();
///找每个集合中,每个点到其他点的最短路的最大值
///maxdis[i]:以i为起点的最短路的最大值
double ans1 = 0;
for(int i = 1; i <= n; i++){
maxdis[i] = 0;
for(int j = 1; j <= n; j++){
if(g[i][j] != INF && maxdis[i] < g[i][j])
maxdis[i] = g[i][j];
}
ans1 = max(ans1, maxdis[i]);
}
///找不在同一集合的点
double ans2 = INF;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
if(g[i][j] == INF){
if(f(x[i], y[i], x[j], y[j]) + maxdis[i] + maxdis[j] < ans2)
ans2 = f(x[i], y[i], x[j], y[j]) + maxdis[i] + maxdis[j];
}
}
}
if(ans1 < ans2) ans1 = ans2;
printf("%.6f\n", ans1);
return 0;
}