#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#define int long long
using namespace std;
const int maxn=505;
const int maxm=200405;
int a[maxn][maxn],b[maxn][maxn],d[maxn<<1],now[maxn<<1],head[maxn<<1],ver[maxm],edge[maxm],nxt[maxm],tot,n,m,s,t;
long double dis[maxn<<1],cost[maxn<<1],l,r,ans;
bool vis[maxn<<1];
queue<int>q;
void addedge(int u,int v,int w,double c){
ver[++tot]=v;
edge[tot]=w;
cost[tot]=c;
nxt[tot]=head[u];
head[u]=tot;
}
void add_edge(int u,int v,int w,double c){
addedge(u,v,w,c);
addedge(v,u,0,-c);
}
bool spfa(){
for(int i=1;i<=2*n+2;i++){
dis[i]=-1e18;
}
memset( vis, 0, sizeof(vis) ) ;
now[s]=head[s];
vis[s]=true;
dis[s]=0;
d[s]=1;
q.push(s);
while(!q.empty()){
int x=q.front();
q.pop();
vis[x]=false;
for(int i=head[x];i;i=nxt[i]){
int y=ver[i],z=edge[i];
double w=cost[i];
if(!z) continue;
if(dis[x]+w>dis[y]){
now[y]=head[y];
dis[y]=dis[x]+w;
d[y]=d[x]+1;
if(!vis[y]){
vis[y]=true;
q.push(y);
}
}
}
}
return dis[t]!=-1e18;
}
int dinic(int x,int flow){
if(x==t) return flow;
int rest=flow;
for(int i=now[x];i&&rest;i=nxt[i]){
now[x]=i;
int y=ver[i],z=edge[i];
double w=cost[i];
if(dis[y]==dis[x]+w&&d[y]==d[x]+1&&z){
int k=dinic(y,min(rest,z));
if(!k) d[y]=0;
edge[i]-=k;
edge[i^1]+=k;
rest-=k;
ans+=(k*w);
}
}
return flow-rest;
}
bool check(double mid){
memset(head,0,sizeof(head));
tot=s=1;
t=2*n+2;
ans=0;
for(int i=1;i<=n;i++)
add_edge(s,i+1,1,0);
for(int i=1;i<=n;i++)
add_edge(n+i+1,t,1,0);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
add_edge(i+1,j+n+1,1,a[i][j]-mid*b[i][j]);
while(spfa()) while(dinic(s,1e9));
return ans>0;
}
signed main(){
scanf("%lld",&n);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
scanf("%lld",&a[i][j]);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
scanf("%lld",&b[i][j]);
r=1e5+5;
double eps=1e-8;
double fuck=0;
while(r-l>eps){
double mid=(l+r)/2.0;
if(check(mid))
fuck=mid,l=mid+eps;
else
r=mid-eps;
}
printf("%0.6lf",fuck);
return 0;
}