#include <bits/stdc++.h>
using namespace std;
template <typename T>
inline T qmin(const T a, const T b) {
  return a < b ? a : b;
}
template <typename T>
inline T qmax(const T a, const T b) {
  return a > b ? a : b;
}
template <typename T>
inline void getmin(T &a, const T b) {
  if (a > b) a = b;
}
template <typename T>
inline void getmax(T &a, const T b) {
  if (a < b) a = b;
}
inline void fileio(string s) {
  freopen((s + ".in").c_str(), "r", stdin);
  freopen((s + ".out").c_str(), "w", stdout);
}
const int inf = 1e9 + 7;
const long long linf = 1e17 + 7;
const int N = 23;
int a[N][N], b[N][N], g[N][N];
int n, k;
bool visx[N], visy[N];
int lx[N], ly[N], slack[N], pre[N], linkx[N], linky[N];
inline void update() {
  int d = inf;
  for (int i = 0; i < n; ++i)
    if (!visy[i]) getmin(d, slack[i]);
  for (int i = 0; i < n; ++i) {
    if (visx[i]) lx[i] -= d;
    if (visy[i])
      ly[i] += d;
    else
      slack[i] -= d;
  }
}
inline void connect(int v) {
  while (~v) linky[v] = pre[v], swap(linkx[pre[v]], v);
}
int q[1005], st, ed;
inline void bfs(int u) {
  st = 0, ed = 1, q[ed] = u, visx[u] = true;
  while (true) {
    while (st < ed) {
      int u = q[++st];
      for (int v = 0; v < n; ++v) {
        if (visy[v]) continue;
        int diff = lx[u] + ly[v] - g[u][v];
        if (diff > slack[v]) continue;
        pre[v] = u;
        if (!diff) {
          visy[v] = true;
          if (~linky[v])
            q[++ed] = linky[v], visx[linky[v]] = true;
          else {
            connect(v);
            return;
          }
        } else {
          slack[v] = diff;
        }
      }
    }
    update();
    for (int v = 0; v < n; ++v) {
      if (!visy[v] && !slack[v]) {
        visy[v] = true;
        if (~linky[v])
          visx[linky[v]] = true, q[++ed] = linky[v];
        else {
          connect(v);
          return;
        }
      }
    }
  }
}
inline int KM() {
  memset(linkx, -1, sizeof(int) * n);
  memset(linky, -1, sizeof(int) * n);
  for (int i = 0; i < n; ++i) {
    ly[i] = 0, lx[i] = g[i][0];
    for (int j = 1; j < n; ++j) getmax(lx[i], g[i][j]);
  }
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) slack[j] = inf, visx[j] = visy[j] = false;
    bfs(i);
  }
  int ans = 0;
  for (int i = 0; i < n; ++i) ans += lx[i] + ly[i];
  return ans;
}
int main() {
  scanf("%d", &n), k = n >> 1;
  for (register int(i) = 0; (i) < (n); ++(i))
    for (register int(j) = 0; (j) < (n); ++(j)) scanf("%d", a[i] + j);
  for (register int(i) = 0; (i) < (n); ++(i))
    for (register int(j) = 0; (j) < (n); ++(j)) scanf("%d", b[i] + j);
  int ans = 0;
  for (int comb = (1 << k) - 1, x, y, z; comb < 1 << n;
       x = comb & -comb, y = comb + x, z = comb & ~y, comb = (z / x >> 1) | y) {
    for (int i = 0; i < n; ++i) {
      if (comb >> i & 1)
        memcpy(g[i], a[i], sizeof(int) * n);
      else
        memcpy(g[i], b[i], sizeof(int) * n);
    }
    getmax(ans, KM());
    if (clock() > 1.8 * CLOCKS_PER_SEC) return printf("%d\n", ans), 0;
  }
  printf("%d\n", ans);
  return 0;
}
