#include <bits/stdc++.h>
namespace IO {
void read() {}
void print() {}
template <typename T, typename... T2>
inline void read(T &x, T2 &...oth) {
  T f = 1;
  x = 0;
  char ch = getchar();
  while (!isdigit(ch)) {
    if (ch == '-') f = -1;
    ch = getchar();
  }
  while (isdigit(ch)) {
    x = x * 10 + ch - 48;
    ch = getchar();
  }
  x *= f;
  read(oth...);
}
}  // namespace IO
const int INF = 0x3f3f3f3f;
const int N = 23;
int n, a[N][N], val[2][N][N];
int match_j[N], val_i[N], val_j[N], dif[N], ans;
bool vis_i[N], vis_j[N];
bool dfs(int i) {
  vis_i[i] = 1;
  for (int j = 0; j < n; j++) {
    if (vis_j[j]) continue;
    int diff = val_i[i] + val_j[j] - a[i][j];
    if (!diff) {
      vis_j[j] = 1;
      if (match_j[j] == -1 || dfs(match_j[j])) {
        match_j[j] = i;
        return true;
      }
    } else {
      dif[j] = std::min(dif[j], diff);
    }
  }
  return false;
}
int KM() {
  memset(match_j, -1, sizeof(match_j));
  memset(val_j, 0, sizeof(val_j));
  int check = 0;
  for (int i = 0; i < n; i++) {
    val_i[i] = a[i][0];
    for (int j = 1; j < n; j++) val_i[i] = std::max(val_i[i], a[i][j]);
    check += val_i[i];
  }
  if (check <= ans) return 0;
  for (int i = 0; i < n; i++) {
    memset(dif, 0x3f, sizeof(dif));
    while (1) {
      memset(vis_i, 0, sizeof(vis_i));
      memset(vis_j, 0, sizeof(vis_j));
      if (dfs(i)) break;
      int d = INF;
      for (int j = 0; j < n; j++)
        if (!vis_j[j]) d = std::min(d, dif[j]);
      for (int j = 0; j < n; j++) {
        if (vis_i[j]) val_i[j] -= d;
        if (vis_j[j])
          val_j[j] += d;
        else
          dif[j] -= d;
      }
    }
  }
  int res = 0;
  for (int i = 0; i < n; i++) res += a[match_j[i]][i];
  return res;
}
int cal(int x) {
  int cnt = 0;
  while (x) {
    x &= (x - 1);
    cnt++;
  }
  return cnt;
}
int main() {
  clock_t lim = clock() + 1.9 * CLOCKS_PER_SEC;
  IO::read(n);
  for (int k = 0; k < 2; k++)
    for (int i = 0; i < n; i++)
      for (int j = 0; j < n; j++) IO::read(val[k][i][j]);
  int S = 1 << n;
  for (int s = 1; s < S; s++) {
    if (cal(s) == n / 2) {
      for (int i = 0; i < n; i++) {
        int index = s >> i & 1;
        index ^= 1;
        for (int j = 0; j < n; j++) a[i][j] = val[index][i][j];
      }
      ans = std::max(ans, KM());
      if (clock() >= lim) break;
    }
  }
  printf("%d\n", ans);
  return 0;
}
