//double <=1e30
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
//#include<queue>
//#include<vector>
//#include<bits/stdc++.h>
#define ll long long
#define ddd printf("-----------------------\n");
using namespace std;
const int maxn=2e2+10 ;
const double inf=1e20;
char s[maxn];
int n,field[maxn],cnt;
double dis[maxn][maxn],lianc[maxn],zhijing[maxn],ans=inf;
struct node{
int x,y;
double dist(const node &p){
return sqrt(1.0*((p.x-x)*(p.x-x)+(p.y-y)*(p.y-y)));
}
}a[maxn];
void dfs(int id,int i)
{
field[i]=id;
for(int j=0;j<n;j++){
if(dis[i][j]<inf&&field[j]==0){
dfs(id,j);
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin>>n;
for(int i=0;i<n;i++) cin>>a[i].x>>a[i].y;
for(int i=0;i<n;i++){
cin>>s;
for(int j=0;j<n;j++){
if(s[j]=='1'||i==j){
dis[i][j]=a[i].dist(a[j]);
}
else dis[i][j]=inf;
}
}
for(int i=0;i<n;i++) if(field[i]==0) dfs(++cnt,i);
for(int k=0;k<n;k++)
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
if(dis[i][j]>dis[i][k]+dis[k][j])
dis[i][j]=dis[i][k]+dis[k][j];
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
if(dis[i][j]<inf)
lianc[i]=max(lianc[i],dis[i][j]);
zhijing[field[i]]=max(zhijing[field[i]],lianc[i]);
}
double tmp=0;
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
if(field[i]!=field[j]){//dis[i][j]<inf&& 都相连了就一定在同一个连通块里面
tmp=max(max(zhijing[field[i]],zhijing[field[j]]),a[i].dist(a[j])+lianc[i]+lianc[j]);
ans=min(tmp,ans);
}
}
}
printf("%.6lf\n",ans);
return 0;
}