#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using db = double;
using str = string;
using pi = pair<int, int>;
using pl = pair<ll, ll>;
using pd = pair<db, db>;
using vi = vector<int>;
using vb = vector<bool>;
using vl = vector<ll>;
using vd = vector<db>;
using vs = vector<str>;
using vpi = vector<pi>;
using vpl = vector<pl>;
using vpd = vector<pd>;
template <class T>
using V = vector<T>;
template <class T, size_t SZ>
using AR = array<T, SZ>;
const int MOD = 1e9 + 7;
const int MX = 2e5 + 5;
const ll INF = 1e18;
const ld PI = acos((ld)-1);
const int xd[4] = {1, 0, -1, 0}, yd[4] = {0, 1, 0, -1};
mt19937 rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count());
constexpr int pct(int x) { return __builtin_popcount(x); }
constexpr int bits(int x) { return 31 - __builtin_clz(x); }
ll cdiv(ll a, ll b) { return a / b + ((a ^ b) > 0 && a % b); }
ll fdiv(ll a, ll b) { return a / b - ((a ^ b) < 0 && a % b); }
template <class T>
bool ckmin(T& a, const T& b) {
  return b < a ? a = b, 1 : 0;
}
template <class T>
bool ckmax(T& a, const T& b) {
  return a < b ? a = b, 1 : 0;
}
template <class T, class U>
T fstTrue(T lo, T hi, U first) {
  hi++;
  assert(lo <= hi);
  while (lo < hi) {
    T mid = lo + (hi - lo) / 2;
    first(mid) ? hi = mid : lo = mid + 1;
  }
  return lo;
}
template <class T, class U>
T lstTrue(T lo, T hi, U first) {
  lo--;
  assert(lo <= hi);
  while (lo < hi) {
    T mid = lo + (hi - lo + 1) / 2;
    first(mid) ? lo = mid : hi = mid - 1;
  }
  return lo;
}
template <class T>
void remDup(vector<T>& v) {
  sort(begin(v), end(v));
  v.erase(unique(begin(v), end(v)), end(v));
}
template <class T, class U>
void erase(T& t, const U& u) {
  auto it = t.find(u);
  assert(it != end(t));
  t.erase(u);
}
template <class T>
void re(complex<T>& c);
template <class T, class U>
void re(pair<T, U>& p);
template <class T>
void re(vector<T>& v);
template <class T, size_t SZ>
void re(AR<T, SZ>& a);
template <class T>
void re(T& x) {
  cin >> x;
}
void re(db& d) {
  str t;
  re(t);
  d = stod(t);
}
void re(ld& d) {
  str t;
  re(t);
  d = stold(t);
}
template <class T, class... U>
void re(T& t, U&... u) {
  re(t);
  re(u...);
}
template <class T>
void re(complex<T>& c) {
  T a, b;
  re(a, b);
  c = {a, b};
}
template <class T, class U>
void re(pair<T, U>& p) {
  re(p.first, p.second);
}
template <class T>
void re(vector<T>& x) {
  for (auto& a : x) re(a);
}
template <class T, size_t SZ>
void re(AR<T, SZ>& x) {
  for (auto& a : x) re(a);
}
str to_string(char c) { return str(1, c); }
str to_string(const char* second) { return (str)second; }
str to_string(str second) { return second; }
str to_string(bool b) { return to_string((int)b); }
template <class T>
str to_string(complex<T> c) {
  stringstream ss;
  ss << c;
  return ss.str();
}
str to_string(vector<bool> v) {
  str res = "{";
  for (int i = (0); i < ((int)(v).size()); ++i) res += char('0' + v[i]);
  res += "}";
  return res;
}
template <size_t SZ>
str to_string(bitset<SZ> b) {
  str res = "";
  for (int i = (0); i < (SZ); ++i) res += char('0' + b[i]);
  return res;
}
template <class T, class U>
str to_string(pair<T, U> p);
template <class T>
str to_string(T v) {
  bool fst = 1;
  str res = "";
  for (const auto& x : v) {
    if (!fst) res += " ";
    fst = 0;
    res += to_string(x);
  }
  return res;
}
template <class T, class U>
str to_string(pair<T, U> p) {
  return to_string(p.first) + " " + to_string(p.second);
}
template <class T>
void pr(T x) {
  cout << to_string(x);
}
template <class T, class... U>
void pr(const T& t, const U&... u) {
  pr(t);
  pr(u...);
}
void ps() { pr("\n"); }
template <class T, class... U>
void ps(const T& t, const U&... u) {
  pr(t);
  if (sizeof...(u)) pr(" ");
  ps(u...);
}
void DBG() { cerr << "]" << endl; }
template <class T, class... U>
void DBG(const T& t, const U&... u) {
  cerr << to_string(t);
  if (sizeof...(u)) cerr << ", ";
  DBG(u...);
}
void setIn(str second) { freopen(second.c_str(), "r", stdin); }
void setOut(str second) { freopen(second.c_str(), "w", stdout); }
void unsyncIO() { cin.tie(0)->sync_with_stdio(0); }
void setIO(str second = "") {
  unsyncIO();
  if ((int)(second).size()) {
    setIn(second + ".in"), setOut(second + ".out");
  }
}
struct MCMF {
  using F = ll;
  using C = ll;
  struct Edge {
    int to, rev;
    F flo, cap;
    C cost;
  };
  int N;
  V<C> p, dist;
  vpi pre;
  V<V<Edge>> adj;
  void init(int _N) {
    N = _N;
    p.resize(N), adj.resize(N), dist.resize(N), pre.resize(N);
  }
  void ae(int u, int v, F cap, C cost) {
    assert(cap >= 0);
    adj[u].push_back({v, (int)(adj[v]).size(), 0, cap, cost});
    adj[v].push_back({u, (int)(adj[u]).size() - 1, 0, 0, -cost});
  }
  void doubleEdge(int u, int v) {
    adj[u].push_back({v, (int)(adj[v]).size(), 0, 1, 0});
    adj[v].push_back({u, (int)(adj[u]).size() - 1, 0, 1, 0});
  }
  bool path(int second, int t) {
    const C inf = numeric_limits<C>::max();
    dist.assign(N, inf);
    using T = pair<C, int>;
    priority_queue<T, vector<T>, greater<T>> todo;
    todo.push({dist[second] = 0, second});
    while ((int)(todo).size()) {
      T x = todo.top();
      todo.pop();
      if (x.first > dist[x.second]) continue;
      for (auto& e : adj[x.second]) {
        if (e.flo < e.cap &&
            ckmin(dist[e.to], x.first + e.cost + p[x.second] - p[e.to]))
          pre[e.to] = {x.second, e.rev}, todo.push({dist[e.to], e.to});
      }
    }
    return dist[t] != inf;
  }
  pair<F, C> calc(int second, int t) {
    assert(second != t);
    for (int _ = (0); _ < (1000); ++_)
      for (int i = (0); i < (N); ++i)
        for (auto& e : adj[i])
          if (e.cap) ckmin(p[e.to], p[i] + e.cost);
    F totFlow = 0;
    C totCost = 0;
    while (path(second, t)) {
      for (int i = (0); i < (N); ++i) p[i] += dist[i];
      F df = numeric_limits<F>::max();
      for (int x = t; x != second; x = pre[x].first) {
        Edge& e = adj[pre[x].first][adj[x][pre[x].second].rev];
        ckmin(df, e.cap - e.flo);
      }
      if (p[t] >= p[second]) break;
      totFlow += df;
      totCost += (p[t] - p[second]) * df;
      for (int x = t; x != second; x = pre[x].first) {
        Edge& e = adj[x][pre[x].second];
        e.flo -= df;
        adj[pre[x].first][e.rev].flo += df;
      }
    }
    return {totFlow, totCost};
  }
};
MCMF M;
int n;
int hsh(int a, int b) { return n * a + b + 2; }
bool valid(int x, int y) { return 0 <= x && x < n && 0 <= y && y < n; }
int main() {
  setIO();
  re(n);
  V<vi> a(n, vi(n));
  re(a);
  0;
  ll ans = 0;
  for (int i = (0); i < (n - 1); ++i) {
    ans += abs(a[i][0] - a[i + 1][0]);
    ans += abs(a[i][n - 1] - a[i + 1][n - 1]);
    ans += abs(a[0][i] - a[0][i + 1]);
    ans += abs(a[n - 1][i] - a[n - 1][i + 1]);
  }
  M.init(2 + n * n);
  for (int i = (0); i < (n); ++i)
    for (int j = (0); j < (n); ++j) {
      if (1 <= a[i][j]) {
        M.ae(0, hsh(i, j), 1, -a[i][j]);
        M.ae(hsh(i, j), 1, 1, a[i][j]);
      } else if (a[i][j] == 0) {
        for (int z = (0); z < (4); ++z) {
          int X = i + xd[z], Y = j + yd[z];
          if (valid(X, Y) && a[X][Y] != -1) {
            if (make_pair(X, Y) < make_pair(i, j) && a[X][Y] == 0) continue;
            M.doubleEdge(hsh(X, Y), hsh(i, j));
          }
        }
      }
    }
  0;
  ps(ans - M.calc(0, 1).second);
}
