#include <bits/stdc++.h>
#pragma comment(linker, "/STACK:66777216")
using namespace std;
int RAND() { return (rand() << 16) + rand(); }
const int N = 22;
int n;
int c[2][N][N], b[N][N];
int A, B;
int so, si, k;
int u[N], v[N];
int a[N][N];
int used[N];
int mark[N];
int mark2[N];
int m[N];
bool gr[N][N];
int minv[N];
bool ok;
void dfs(int k) {
  mark[k] = true;
  if (!used[k]) return;
  for (int j = 1; j <= (int)(n); ++j)
    minv[j] = min(minv[j], a[k][j] - u[k] - v[j]);
  for (int j = 1; j <= (int)(n); ++j) {
    if (a[k][j] == u[k] + ::v[j] && !mark2[j]) {
      mark2[j] = true;
      if (m[j] == -1)
        ok = true;
      else if (!mark[m[j]])
        dfs(m[j]);
    }
  }
}
bool augment(int v) {
  if (!used[v]) return false;
  if (mark[v]) return false;
  mark[v] = true;
  for (int j = 1; j <= (int)(n); ++j) {
    if (a[v][j] == u[v] + ::v[j]) {
      if (m[j] == -1 || augment(m[j])) {
        m[j] = v;
        return true;
      }
    }
  }
  return false;
}
void iterate(int i) {
  used[i] = true;
  u[i] = 0;
  for (int j = 1; j <= (int)(n); ++j) {
    u[i] = min(u[i], a[i][j] - v[j]);
    mark[j] = 0;
    mark2[j] = 0;
  }
  --u[i];
  mark[i] = 1;
  for (int j = 1; j <= (int)(n); ++j) minv[j] = a[i][j] - u[i] - v[j];
  while (1) {
    pair<int, int> mi(0, -1);
    for (int j = 1; j <= (int)(n); ++j)
      if (!mark2[j] && (mi.second == -1 || minv[j] <= mi.first))
        mi = make_pair(minv[j], j);
    for (int j = 1; j <= (int)(n); ++j) {
      if (mark[j] && used[j]) u[j] += mi.first;
      if (mark2[j])
        v[j] -= mi.first;
      else
        minv[j] -= mi.first;
    }
    vector<int> ve;
    bool flag2 = false;
    for (int j = 1; j <= (int)(n); ++j) {
      if (!mark2[j] && minv[j] == 0) {
        ve.push_back(j);
        if (m[j] == -1) flag2 = true;
      }
    }
    if (flag2) {
      for (int j = 1; j <= (int)(n); ++j) mark[j] = false;
      augment(i);
      break;
    } else {
      ok = false;
      for (int j = 0; j < (int)(((int)((ve).size()))); ++j) {
        mark2[ve[j]] = true;
        int to = m[ve[j]];
        if (!mark[to]) dfs(to);
      }
      if (ok) {
        for (int j = 1; j <= (int)(n); ++j) mark[j] = false;
        augment(i);
        break;
      }
    }
  }
}
void precalc(int mask) {
  for (int i = 1; i <= (int)(n); ++i) {
    m[i] = -1;
    if (mask & (1 << (i - 1))) {
      for (int j = 1; j <= (int)(n); ++j) a[i][j] = c[1][i][j];
    } else {
      for (int j = 1; j <= (int)(n); ++j) a[i][j] = c[0][i][j];
    }
  }
  for (int i = 1; i <= (int)(n); ++i) m[i] = -1;
  for (int i = 1; i <= (int)(n); ++i) iterate(i);
}
const int inf = 1000000 + 5;
void solve() {
  scanf("%d", &n);
  for (int i = 1; i <= (int)(n); ++i)
    for (int j = 1; j <= (int)(n); ++j) scanf("%d", &c[0][i][j]);
  for (int i = 1; i <= (int)(n); ++i)
    for (int j = 1; j <= (int)(n); ++j) scanf("%d", &c[1][i][j]);
  for (int i = 1; i <= (int)(n); ++i)
    for (int j = 1; j <= (int)(n); ++j) {
      c[0][i][j] = inf - c[0][i][j];
      c[1][i][j] = inf - c[1][i][j];
    }
  int cr = 0;
  for (int i = 0; i < (int)(n / 2); ++i) cr += (1 << i);
  bool flag = false;
  int ans = 0;
  for (int T = 0; T < (1 << n); ++T) {
    int mask = (T ^ (T >> 1));
    if (mask == cr) {
      precalc(mask);
      flag = true;
      int res = 0;
      for (int k = 1; k <= (int)(n); ++k) res += inf - a[m[k]][k];
      ans = max(res, ans);
      continue;
    }
    if (!flag) continue;
    int q = 0;
    for (int j = 0; j < (int)(n); ++j)
      if (mask & (1 << j)) ++q;
    if (q != (n / 2)) continue;
    A = -1;
    B = -1;
    for (int j = 0; j < (int)(n); ++j) {
      if (!(mask & (1 << j)) && (cr & (1 << j))) A = j;
      if ((mask & (1 << j)) && !(cr & (1 << j))) B = j;
    }
    ++A;
    ++B;
    for (int j = 1; j <= (int)(n); ++j) {
      a[A][j] = c[0][A][j];
      a[B][j] = c[1][B][j];
    }
    used[A] = false;
    used[B] = false;
    for (int j = 1; j <= (int)(n); ++j) {
      if (m[j] == A) m[j] = -1;
      if (m[j] == B) m[j] = -1;
    }
    iterate(A);
    iterate(B);
    int res = 0;
    for (int j = 1; j <= (int)(n); ++j) res += inf - a[m[j]][j];
    ans = max(res, ans);
    cr = mask;
  }
  printf("%d\n", ans);
}
void testgen() {
  FILE* f = fopen("input.txt", "w");
  fclose(f);
}
int main() {
  cout << fixed;
  cout.precision(16);
  cerr << fixed;
  cerr.precision(3);
  solve();
  return 0;
}
