#include <bits/stdc++.h>
using namespace std;
inline long long rd() {
  long long x = 0;
  int ch = getchar(), f = 1;
  while (!isdigit(ch) && (ch != '-') && (ch != EOF)) ch = getchar();
  if (ch == '-') {
    f = -1;
    ch = getchar();
  }
  while (isdigit(ch)) {
    x = (x << 1) + (x << 3) + ch - '0';
    ch = getchar();
  }
  return x * f;
}
inline void rt(long long x) {
  if (x < 0) putchar('-'), x = -x;
  if (x >= 10)
    rt(x / 10), putchar(x % 10 + '0');
  else
    putchar(x + '0');
}
const int maxn = 22;
int ans = 0, n, a[maxn][maxn], b[maxn][maxn];
int slack, link[maxn], lx[maxn], ly[maxn], mp[maxn][maxn], suf[maxn], tim;
int visx[maxn], visy[maxn];
bool find(int u) {
  if (visx[u] == tim) return 0;
  visx[u] = tim;
  for (int i = 1; i <= (int)n; i++) {
    if (visy[i] == tim) continue;
    int tmp = lx[u] + ly[i] - mp[u][i];
    if (!tmp) {
      visy[i] = tim;
      if (!link[i] || find(link[i])) {
        link[i] = u;
        return 1;
      }
    } else
      slack = min(slack, tmp);
  }
  return 0;
}
void dfs(int ps, int rem) {
  if (ps == n + 1) {
    int ret = 0;
    for (int i = 1; i <= (int)n; i++) ret += lx[i] + ly[i];
    ans = max(ans, ret);
    if (clock() / (double)(CLOCKS_PER_SEC) >= 0.6) rt(ans), exit(0);
    return;
  }
  int now = 0;
  for (int i = 1; i <= (int)n; i++) now += mp[link[i]][i];
  if (now + suf[ps] <= ans) return;
  int LINK[maxn], LX[maxn], LY[maxn];
  memcpy(LINK, link, sizeof LINK), memcpy(LX, lx, sizeof LX),
      memcpy(LY, ly, sizeof LY);
  if (rem) {
    lx[ps] = 0;
    for (int i = 1; i <= (int)n; i++)
      mp[ps][i] = a[ps][i], lx[ps] = max(lx[ps], a[ps][i]);
    for (;;) {
      ++tim, slack = (1 << 29);
      if (find(ps)) break;
      for (int i = 1; i <= (int)ps; i++)
        if (visx[i] == tim) lx[i] -= slack;
      for (int i = 1; i <= (int)n; i++)
        if (visy[i] == tim) ly[i] += slack;
    }
    dfs(ps + 1, rem - 1);
    memcpy(link, LINK, sizeof LINK), memcpy(lx, LX, sizeof LX),
        memcpy(ly, LY, sizeof LY);
  }
  if (rem != n - ps + 1) {
    lx[ps] = 0;
    for (int i = 1; i <= (int)n; i++)
      mp[ps][i] = b[ps][i], lx[ps] = max(lx[ps], b[ps][i]);
    for (;;) {
      ++tim, slack = (1 << 29);
      if (find(ps)) break;
      for (int i = 1; i <= (int)ps; i++)
        if (visx[i] == tim) lx[i] -= slack;
      for (int i = 1; i <= (int)n; i++)
        if (visy[i] == tim) ly[i] += slack;
    }
    dfs(ps + 1, rem);
    memcpy(link, LINK, sizeof LINK), memcpy(lx, LX, sizeof LX),
        memcpy(ly, LY, sizeof LY);
  }
}
int main() {
  n = rd();
  for (int i = 1; i <= (int)n; i++)
    for (int j = 1; j <= (int)n; j++)
      a[i][j] = rd(), a[i][0] = max(a[i][0], a[i][j]);
  for (int i = 1; i <= (int)n; i++)
    for (int j = 1; j <= (int)n; j++)
      b[i][j] = rd(), b[i][0] = max(b[i][0], b[i][j]);
  for (int i = 1; i <= (int)n; i++) suf[i] = max(a[i][0], b[i][0]);
  for (int i = n - 1; i >= (int)1; i--) suf[i] += suf[i + 1];
  dfs(1, n / 2);
  rt(ans);
}
