#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#define ll long long
#define INF 1000000000
#define p(x) ('0'<=x&&x<='9')
#define For(i,l,r) for(int i=l;i<=r;i++)
char cc; int C;
template <class T>
void read( T &x )
{
x=0; cc=getchar(); C=1;
while(!p(cc)) { if(cc=='-') C=-1; cc=getchar(); }
while(p(cc)) { x=x*10+cc-48; cc=getchar(); }
x*=C;
}
using namespace std;
#define EE 80000
#define N 300
#define source 0
#define sink N-1
#define source_ N-2
#define sink_ N-3
struct Tedge
{
int to,flow;
}edge[EE];
int e_tot,nxt[EE],fst[N];
#define E edge[i]
#define FLOW E.flow
#define TO E.to
#define NXT nxt[i]
#define calc(i) (n+i)
void add_e(int from,int to,int flow)
{
static int &i=e_tot;
TO=to; FLOW=flow; NXT=fst[from]; fst[from]=i++;
TO=from; FLOW=0; NXT=fst[to]; fst[to]=i++;
}
double a[N][N];
int imp[N],in[N];
int n,S,T;
void init()
{
int _;
memset(fst,-1,sizeof(fst));
read(n);
For(i,1,n)
for(int j=1;j<=n;j++) scanf("%lf",&a[i][j]);
For(i,1,n-1)
for(int j=1;j<n;j++)
{
_=(int)floor(a[i][j]);
if(ceil(a[i][j])!=_) add_e(i,calc(j),1);
in[i]-=_; in[calc(j)]+=_;
}
For(i,1,n-1)
{
_=floor(a[i][n]);
in[i]+=_;
in[source]-=_;
if(ceil(a[i][n])!=_) add_e(source,i,1);
}
For(i,1,n-1)
{
_=floor(a[n][i]);
in[sink]+=_;
in[calc(i)]-=_;
if(ceil(a[n][i])!=_) add_e(calc(i),sink,1);
}
add_e(sink,source,INF);
For(i,0,N-1) if(in[i])
{
in[i]>0?add_e(source_,i,in[i]):add_e(i,sink_,-in[i]);
imp[i]=e_tot-2;
}
}
int cnt[N],d[N];
bool bfs()
{
memset(d,0,sizeof(d));
memset(cnt,0,sizeof(cnt));
static int queue[65540],x;
static unsigned short int he=0,ta=0;
queue[++he]=T;
d[T]=1;
while(he!=ta)
{
x=queue[++ta]; cnt[d[x]]++;
for(int i=fst[x];~i;i=NXT) if(!d[TO]&&edge[i^1].flow)
{ d[TO]=d[x]+1; queue[++he]=TO; }
}
return d[S];
}
void cp(int &x,int y) { x>y?x=y:x; }
int p[N];
int Augment()
{
static int node,c,i;
node=T; c=INF;
while(node!=S)
{
i=p[node]; cp(c,FLOW);
node=edge[i^1].to;
}
node=T;
while(node!=S)
{
i=p[node]; FLOW-=c;
i^=1; FLOW+=c;
node=TO;
}
return c;
}
int ISAP()
{
static int node,cur[N],ret;
static bool flag;
if(!bfs()) return 0;
node=S; ret=0;
for(int i=0;i<N;i++) cur[i]=fst[i];
while(d[S]<n*2+5)
{
if(node==T)
{
ret+=Augment();
node=S;
}
flag=false;
for(int i=cur[node];~i;i=NXT) if(d[TO]==d[node]-1&&FLOW)
{
p[TO]=i;
cur[node]=i;
node=TO;
flag=true;
break;
}
if(flag) continue;
int M=N-1;
if(!--cnt[d[node]]) break;
for(int i=fst[node];~i;i=NXT) if(FLOW) cp(M,d[TO]+1);
cnt[d[node]=M]++;
cur[node]=fst[node];
node==S?node:node=edge[p[node]^1].to;
}
return ret;
}
bool check()
{
For(i,0,N-1) if(imp[i]) if(edge[imp[i]].flow) return false;
return true;
}
int main()
{
init();
S=source_,T=sink_;
ISAP();
// printf("%d\n",ISAP());
if(!check())
{
puts("-1");
return 0;
}
S=source,T=sink;
printf("%d\n",ISAP()*3);
return 0;
}