import java.io._
import java.util.StringTokenizer
import scala.util.control.Breaks.{breakable,break}
import scala.collection.mutable.Map


object Main extends App {
  val in = new InputReader(System.in)
  val pw = new PrintWriter(System.out)

  val N, C = in.next().toInt
  val D = Array.ofDim[Int](C+1, C+1)
  val c = Array.ofDim[Int](N+1, N+1)

  for (y <- 1 to C; x <- 1 to C) {
    D(y)(x) = in.next().toInt
  }
  for (y <- 1 to N; x <- 1 to N) {
    c(y)(x) = in.next().toInt
  }



  val map0: Map[Int, Int] = Map()
  val map1: Map[Int, Int] = Map()
  val map2: Map[Int, Int] = Map()

  val maps = Array(map0, map1, map2)

  for (y <- 1 to N; x <- 1 to N) {
    val nowi = (x + y) % 3
    val now = maps(nowi)
    val v = c(y)(x)

    if(now.contains(v)) {
      now(v) += 1
    }
    else {
      now += (v -> 1)
    }
  }

  val col0 = new Array[(Long, Int)](C) // (score, color - 1)
  for (i <- 1 to C) {
    var tmp = 0L
    for((k, v) <- map0) {
      tmp += D(k)(i) * v
    }
    col0(i-1) = (tmp, i-1)
  }

  val col1 = new Array[(Long, Int)](C) // (score, color - 1)
  for (i <- 1 to C) {
    var tmp = 0L
    for((k, v) <- map1) {
      tmp += D(k)(i) * v
    }
    col1(i-1) = (tmp, i-1)
  }

  val col2 = new Array[(Long, Int)](C) // (score, color - 1)
  for (i <- 1 to C) {
    var tmp = 0L
    for((k, v) <- map2) {
      tmp += D(k)(i) * v
    }
    col2(i-1) = (tmp, i-1)
  }

  var ans = Long.MaxValue
  for {
    (v0, col0) <- col0.sorted.take(3)
    (v1, col1) <- col1.sorted.take(3)
    (v2, col2) <- col2.sorted.take(3)
  } {
    if (col0 != col1 && col1 != col2 && col2 != col0) {
      ans = Math.min(ans, v0+v1+v2)
    }
  }

  println(ans)
}


class InputReader(stream: InputStream) {
  private val reader = new BufferedReader(new InputStreamReader(stream))
  private var tokenizer: StringTokenizer = new StringTokenizer(reader.readLine())
  def next(): String = {
    while (!tokenizer.hasMoreTokens()) {
      tokenizer = new StringTokenizer(reader.readLine())
    }
    tokenizer.nextToken()
  }
}
