#pragma GCC optimize("O3")
#pragma GCC target("sse4")

#include <bits/stdc++.h>

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <typeinfo>

using namespace std;
using namespace __gnu_pbds;

typedef long long ll;
typedef long double ld;
typedef complex<ld> cd;

typedef pair<int, int> pi;
typedef pair<ll, ll> pl;
typedef pair<ld, ld> pd;

typedef vector<int> vi;
typedef vector<ld> vd;
typedef vector<ll> vl;
typedef vector<pi> vpi;
typedef vector<pl> vpl;
typedef vector<cd> vcd;

template <class T>
using Tree =
    tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

#define rep(i, a, b) for (int i = a; i < b; i++)
#define rrep(i, a, b) for (int i = a; i >= b; i--)
#define FOR(i, a, b) for (int i = a; i < (b); i++)
#define F0R(i, a) for (int i = 0; i < (a); i++)
#define FORd(i, a, b) for (int i = (b)-1; i >= a; i--)
#define F0Rd(i, a) for (int i = (a)-1; i >= 0; i--)

#define sz(x) (int)(x).size()
#define mp make_pair
#define pb push_back
#define f first
#define s second
#define lb lower_bound
#define ub upper_bound
#define all(x) x.begin(), x.end()
#define shandom_ruffle random_shuffle

const int MOD = 1000000007;
const ll INF = 1e18;
const int MX = 100001;  // check the limits, dummy

typedef long long ll;
const int inf = INT_MAX / 2;
const ll infl = 1LL << 60;
template <class T>
bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T>
bool chmin(T &a, const T &b) {
  if (b < a) {
    a = b;
    return 1;
  }
  return 0;
}

template <class T>
void print(const vector<T> v) {
  cout << "[ ";
  F0R(i, v.size()) { cout << v[i] << ' '; }
  cout << "]" << '\n';
}

int mod(int i, int j) {
  return (i % j) < 0 ? (i % j) + 0 + (j < 0 ? -j : j) : (i % j + 0);
}

unsigned euclidean_gcd(unsigned a, unsigned b) {
  if (a < b) return euclidean_gcd(b, a);
  unsigned r;
  while ((r = a % b)) {
    a = b;
    b = r;
  }
  return b;
}

int middleOfThree(int a, int b, int c) {
  // Checking for b
  if ((a < b && b < c) || (c < b && b < a)) return b;

  // Checking for a
  else if ((b < a && a < c) || (c < a && a < b))
    return a;

  else
    return c;
}

int vector_finder(std::vector<int> vec, int number) {
  auto itr = std::find(vec.begin(), vec.end(), number);
  size_t index = std::distance(vec.begin(), itr);
  if (index != vec.size()) {  // 発見できたとき
    return 1;
  } else {  // 発見できなかったとき
    return 0;
  }
}
// --------------------------------------------------------
// This is tool
// --------------------------------------------------------

// string S;
// ll cnt[2020];

void Main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  int N, C;
  cin >> N >> C;

  vector<vector<int>> D(C, vector<int>(C, 0));
  vector<vector<int>> c(N, vector<int>(N, 0));
  // 各あまりの全てがその色に変更する時のコスト
  vector<vector<int>> A(3, vector<int>(C, 0));

  FOR(i, 0, C) {
    FOR(j, 0, C) {
      cin >> D[i][j];
      // cout << D[i][j];
    }
  }
  FOR(i, 0, N) {
    FOR(j, 0, N) {
      cin >> c[i][j];
      // cout << c[i][j];
    }
  }

  // nnの行列に対してi+j%3ごとに分離
  FOR(i, 0, N) {
    FOR(j, 0, N) {
      // 0 indexなので+2する
      if ((i + j + 2) % 3 == 0) {
        // 全ての色に対して
        FOR(k, 0, C) {
          // cout << "k:" << k << endl;
          // 変更前から変更後への違和感をたす
          // cout << A[2][k] << endl;
          // cout << c[i][j] << endl;
          // cout << k << endl;
          // cout << D[c[i][j] - 1][k] << endl;
          A[0][k] += D[c[i][j] - 1][k];
        }
      } else if ((i + j + 2) % 3 == 1) {
        FOR(k, 0, C) {
          // cout << "i:" << i << " j:" << j << endl;
          A[1][k] += D[c[i][j] - 1][k];
        }
      } else if ((i + j + 2) % 3 == 2) {
        FOR(k, 0, C) {
          // cout << "i:" << i << " j:" << j << endl;
          A[2][k] += D[c[i][j] - 1][k];
        }
      }
    }
  }
  // cout << A[0][0] << endl;
  // cout << A[0][1] << endl;
  // cout << A[0][2] << endl;

  // A[0~2][0~C-1]に対してどの組み合わせが一番、違和感が小さいか
  ll iwakan = INF;
  FOR(i, 0, C) {
    FOR(j, 0, C) {
      FOR(k, 0, C) {
        if ((i != j) && (j != k) && (k != i)) {
          ll total = A[0][i] + A[1][j] + A[2][k];
          iwakan = min(iwakan, total);
        }
      }
    }
  }
  cout << iwakan << endl;
}

int main() {
  std::cin.tie(nullptr);
  std::ios_base::sync_with_stdio(false);
  std::cout << std::fixed << std::setprecision(15);
  Main();
}

Measured memory_bytes: 1280