import sys

sys.setrecursionlimit(1000000)

#def input():

#    return sys.stdin.readline()[:-1]



'''

n=int(input())

for i in range(n):

    a[i]=int(input())

    a[i],b[i]=map(int,input().split())

a=[int(x) for x in input().split()]

n,m=map(int,input.split())

from operator import itemgetter

a = [(1, "c", 1), (1, "b", 3), (2, "a", 0), (1, "a", 2)]

print(sorted(a))  # 0 番目の要素でソート、先頭の要素が同じなら 1 番目以降の要素も見る

print(sorted(a, key=itemgetter(0)))  # 0 番目の要素だけでソート

print(sorted(a, key=itemgetter(0, 2)))  # 0 番目と 2 番目の要素でソート

print(sorted(a, key=lambda x: x[0] * x[2]))  # 0 番目の要素 * 2 番目の要素でソート

print(sorted(a, reverse=True))  # 降順にソート

a.sort()  # 破壊的にソート、sorted() よりも高速

try: # エラーキャッチ list index out of range

    for i in range():

        k=b[i]

except IndexError as e:

    print(i)

'''



test_data1 = '''\

2 3

0 1 1

1 0 1

1 4 0

1 2

3 3

'''



test_data2 = '''\

4 3

0 12 71

81 0 53

14 92 0

1 1 2 1

2 1 1 2

2 2 1 3

1 1 2 2

'''



test_data3 = '''\



'''

td_num=2



def GetTestData(index):

    if index==1:

        return test_data1

    if index==2:

        return test_data2

    if index==3:

        return test_data3



if False:

    with open("../test.txt", mode='w') as f:

        f.write(GetTestData(td_num))

    with open("../test.txt") as f:

        # Start Input code ---------------------------------------

        N,C=list(map(int,f.readline().split()))

        c=[[0 for j in range(C)] for i in range(3)]

        D=[[0 for i in range(C)] for j in range(C)]

        for i in range(C):

            D[i]=[int(x) for x in f.readline().split()]

        for x in range(N):

            y=0

            for j in f.readline().split():

                c[(x+y)%3][int(j)-1]+=1

                y+=1

        # End Input code ---------------------------------------

else:

    if 0==0:

        # Start Input code ---------------------------------------

        N,C=list(map(int,input().split()))

        c=[[0 for j in range(C)] for i in range(3)]

        D=[[0 for i in range(C)] for j in range(C)]

        for i in range(C):

            D[i]=[int(x) for x in input().split()]

        for x in range(N):

            y=0

            for j in input().split():

                c[(x+y)%3][int(j)-1]+=1

                y+=1

        # End Input code ---------------------------------------



St=[[0 for i in range(3)] for j in range(C)]

ans=10**20

for c1 in range(C):

    for c2 in range(C):

        for c3 in range(C):

            cc=0

            dd=0

            for i in range(C):

                cc+=c[0][i]*D[i][c1]

                cc+=c[1][i]*D[i][c2]

                cc+=c[2][i]*D[i][c3]

                

                dd+=c[0][i]*D[c1][i]

                dd+=c[1][i]*D[c2][i]

                dd+=c[2][i]*D[c3][i]

            if len(set([c1,c2,c3]))==3:

                ans=min(ans,cc)

            #print(ans,c,D)

#print('N,C=',N,C,'D=',D,'c=',c,'St=',St)

print(ans)

from heapq import heappush,heappop,heapify

from collections import deque,defaultdict,Counter

import itertools

from functools import *

from itertools import permutations,combinations,groupby

import sys

import bisect

import string

import math

import time

import random

def Golf():

    *a,=map(int,open(0))

def S_():

    return input()

def IS():

    return input().split()

def LS():

    return [i for i in input().split()]

def I():

    return int(input())

def MI():

    return map(int,input().split())

def LI():

    return [int(i) for i in input().split()]

def LI_():

    return [int(i)-1 for i in input().split()]

def NI(n):

    return [int(input()) for i in range(n)]

def NI_(n):

    return [int(input())-1 for i in range(n)]

def StoI():

    return [ord(i)-97 for i in input()]

def ItoS(nn):

    return chr(nn+97)

def LtoS(ls):

    return ''.join([chr(i+97) for i in ls])

def GI(V,E,Directed=False,index=0):

    org_inp=[]

    g=[[] for i in range(n)]

    for i in range(E):

        inp=LI()

        org_inp.append(inp)

        if index==0:

            inp[0]-=1

            inp[1]-=1

        if len(inp)==2:

            a,b=inp

            g[a].append(b)

            if not Directed:

                g[b].append(a)

        elif len(inp)==3:

            a,b,c=inp

            aa=(inp[0],inp[2])

            bb=(inp[1],inp[2])

            g[a].append(bb)

            if not Directed:

                g[b].append(aa)

    return g,org_inp

def GGI(h,w,search=None,replacement_of_found='.',mp_def={'#':1,'.':0}):

#h,w,g,sg=GGI(h,w,search=['S','G'],replacement_of_found='.',mp_def={'#':1,'.':0}) # sample usage

    mp=[1]*(w+2)

    found={}

    for i in range(h):

        s=input()

        for char in search:

            if char in s:

                found[char]=((i+1)*(w+2)+s.index(char)+1)

                mp_def[char]=mp_def[replacement_of_found]

        mp+=[1]+[mp_def[j] for j in s]+[1]

    mp+=[1]*(w+2)

    return h+2,w+2,mp,found

def bit_combination(k,n=2):

    rt=[]

    for tb in range(n**k):

        s=[tb//(n**bt)%n for bt in range(k)]

        rt+=[s]

    return rt

def show(*inp,end='\n'):

    if show_flg:

        print(*inp,end=end)

YN=['YES','NO']



mo=10**9+7

inf=float('inf')

l_alp=string.ascii_lowercase

u_alp=string.ascii_uppercase

ts=time.time()

#sys.setrecursionlimit(10**7)

input=lambda: sys.stdin.readline().rstrip()

 

def ran_input():

    import random

    n=random.randint(4,16)

    rmin,rmax=1,10

    a=[random.randint(rmin,rmax) for _ in range(n)]

    return n,a



show_flg=False

show_flg=True



ans=inf



n,c=LI()

d=[defaultdict(int)for i in' '*3]

f=[]

for i in range(c):

    f+=[LI()]

for i in range(n):

    x=LI()

    for j in range(n):

        d[(i+j)%3][x[j]-1]+=1



for i in range(c):

    for j in range(c):

        for k in range(c):

            if len(set([i,j,k]))<3:

                continue

            tmp=0

        

            for col,cnt in d[0].items():

                tmp+=f[col][i]*cnt

            for col,cnt in d[1].items():

                tmp+=f[col][j]*cnt

            for col,cnt in d[2].items():

                tmp+=f[col][k]*cnt

            ans=min(ans,tmp)



print(ans)

import sys

sys.setrecursionlimit(1000000)
# def input():
#    return sys.stdin.readline()[:-1]
"""
n=int(input())
for i in range(n):
    a[i]=int(input())
    a[i],b[i]=map(int,input().split())
a=[int(x) for x in input().split()]
n,m=map(int,input.split())
from operator import itemgetter
a = [(1, "c", 1), (1, "b", 3), (2, "a", 0), (1, "a", 2)]
print(sorted(a))  # 0 番目の要素でソート、先頭の要素が同じなら 1 番目以降の要素も見る
print(sorted(a, key=itemgetter(0)))  # 0 番目の要素だけでソート
print(sorted(a, key=itemgetter(0, 2)))  # 0 番目と 2 番目の要素でソート
print(sorted(a, key=lambda x: x[0] * x[2]))  # 0 番目の要素 * 2 番目の要素でソート
print(sorted(a, reverse=True))  # 降順にソート
a.sort()  # 破壊的にソート、sorted() よりも高速
try: # エラーキャッチ list index out of range
    for i in range():
        k=b[i]
except IndexError as e:
    print(i)
"""
test_data1 = """\
2 3
0 1 1
1 0 1
1 4 0
1 2
3 3
"""
test_data2 = """\
4 3
0 12 71
81 0 53
14 92 0
1 1 2 1
2 1 1 2
2 2 1 3
1 1 2 2
"""
test_data3 = """\
"""
td_num = 2


def GetTestData(index):
    if index == 1:
        return test_data1
    if index == 2:
        return test_data2
    if index == 3:
        return test_data3


if False:
    with open("../test.txt", mode="w") as f:
        f.write(GetTestData(td_num))
    with open("../test.txt") as f:
        # Start Input code ---------------------------------------
        N, C = list(map(int, f.readline().split()))
        c = [[0 for j in range(C)] for i in range(3)]
        D = [[0 for i in range(C)] for j in range(C)]
        for i in range(C):
            D[i] = [int(x) for x in f.readline().split()]
        for x in range(N):
            y = 0
            for j in f.readline().split():
                c[(x + y) % 3][int(j) - 1] += 1
                y += 1
        # End Input code ---------------------------------------
else:
    if 0 == 0:
        # Start Input code ---------------------------------------
        N, C = list(map(int, input().split()))
        c = [[0 for j in range(C)] for i in range(3)]
        D = [[0 for i in range(C)] for j in range(C)]
        for i in range(C):
            D[i] = [int(x) for x in input().split()]
        for x in range(N):
            y = 0
            for j in input().split():
                c[(x + y) % 3][int(j) - 1] += 1
                y += 1
        # End Input code ---------------------------------------
St = [[0 for i in range(3)] for j in range(C)]
ans = 10**20
for c1 in range(C):
    for c2 in range(C):
        for c3 in range(C):
            cc = 0
            dd = 0
            for i in range(C):
                cc += c[0][i] * D[i][c1]
                cc += c[1][i] * D[i][c2]
                cc += c[2][i] * D[i][c3]
                dd += c[0][i] * D[c1][i]
                dd += c[1][i] * D[c2][i]
                dd += c[2][i] * D[c3][i]
            if len(set([c1, c2, c3])) == 3:
                ans = min(ans, cc)
            # print(ans,c,D)
# print('N,C=',N,C,'D=',D,'c=',c,'St=',St)
print(ans)

from heapq import heappush, heappop, heapify
from collections import deque, defaultdict, Counter
import itertools
from functools import *
from itertools import permutations, combinations, groupby
import sys
import bisect
import string
import math
import time
import random


def Golf():
    (*a,) = map(int, open(0))


def S_():
    return input()


def IS():
    return input().split()


def LS():
    return [i for i in input().split()]


def I():
    return int(input())


def MI():
    return map(int, input().split())


def LI():
    return [int(i) for i in input().split()]


def LI_():
    return [int(i) - 1 for i in input().split()]


def NI(n):
    return [int(input()) for i in range(n)]


def NI_(n):
    return [int(input()) - 1 for i in range(n)]


def StoI():
    return [ord(i) - 97 for i in input()]


def ItoS(nn):
    return chr(nn + 97)


def LtoS(ls):
    return "".join([chr(i + 97) for i in ls])


def GI(V, E, Directed=False, index=0):
    org_inp = []
    g = [[] for i in range(n)]
    for i in range(E):
        inp = LI()
        org_inp.append(inp)
        if index == 0:
            inp[0] -= 1
            inp[1] -= 1
        if len(inp) == 2:
            a, b = inp
            g[a].append(b)
            if not Directed:
                g[b].append(a)
        elif len(inp) == 3:
            a, b, c = inp
            aa = (inp[0], inp[2])
            bb = (inp[1], inp[2])
            g[a].append(bb)
            if not Directed:
                g[b].append(aa)
    return g, org_inp


def GGI(h, w, search=None, replacement_of_found=".", mp_def={"#": 1, ".": 0}):
    # h,w,g,sg=GGI(h,w,search=['S','G'],replacement_of_found='.',mp_def={'#':1,'.':0}) # sample usage
    mp = [1] * (w + 2)
    found = {}
    for i in range(h):
        s = input()
        for char in search:
            if char in s:
                found[char] = (i + 1) * (w + 2) + s.index(char) + 1
                mp_def[char] = mp_def[replacement_of_found]
        mp += [1] + [mp_def[j] for j in s] + [1]
    mp += [1] * (w + 2)
    return h + 2, w + 2, mp, found


def bit_combination(k, n=2):
    rt = []
    for tb in range(n**k):
        s = [tb // (n**bt) % n for bt in range(k)]
        rt += [s]
    return rt


def show(*inp, end="\n"):
    if show_flg:
        print(*inp, end=end)


YN = ["YES", "NO"]
mo = 10**9 + 7
inf = float("inf")
l_alp = string.ascii_lowercase
u_alp = string.ascii_uppercase
ts = time.time()
# sys.setrecursionlimit(10**7)
input = lambda: sys.stdin.readline().rstrip()


def ran_input():
    import random

    n = random.randint(4, 16)
    rmin, rmax = 1, 10
    a = [random.randint(rmin, rmax) for _ in range(n)]
    return n, a


show_flg = False
show_flg = True
ans = inf
n, c = LI()
d = [defaultdict(int) for i in " " * 3]
f = []
for i in range(c):
    f += [LI()]
for i in range(n):
    x = LI()
    for j in range(n):
        d[(i + j) % 3][x[j] - 1] += 1
for i in range(c):
    for j in range(c):
        for k in range(c):
            if len(set([i, j, k])) < 3:
                continue
            tmp = 0
            for col, cnt in d[0].items():
                tmp += f[col][i] * cnt
            for col, cnt in d[1].items():
                tmp += f[col][j] * cnt
            for col, cnt in d[2].items():
                tmp += f[col][k] * cnt
            ans = min(ans, tmp)
print(ans)

+from heapq import heappush, heappop, heapify +from collections import deque, defaultdict, Counter +import itertools +from functools import * +from itertools import permutations, combinations, groupby - -sys.setrecursionlimit(1000000) -# def input(): -#    return sys.stdin.readline()[:-1] -""" -n=int(input()) -for i in range(n): -    a[i]=int(input()) -    a[i],b[i]=map(int,input().split()) -a=[int(x) for x in input().split()] -n,m=map(int,input.split()) -from operator import itemgetter -a = [(1, "c", 1), (1, "b", 3), (2, "a", 0), (1, "a", 2)] -print(sorted(a))  # 0 番目の要素でソート、先頭の要素が同じなら 1 番目以降の要素も見る -print(sorted(a, key=itemgetter(0)))  # 0 番目の要素だけでソート -print(sorted(a, key=itemgetter(0, 2)))  # 0 番目と 2 番目の要素でソート -print(sorted(a, key=lambda x: x[0] * x[2]))  # 0 番目の要素 * 2 番目の要素でソート -print(sorted(a, reverse=True))  # 降順にソート -a.sort()  # 破壊的にソート、sorted() よりも高速 -try: # エラーキャッチ list index out of range -    for i in range(): -        k=b[i] -except IndexError as e: -    print(i) -""" -test_data1 = """\ -2 3 -0 1 1 -1 0 1 -1 4 0 -1 2 -3 3 -""" -test_data2 = """\ -4 3 -0 12 71 -81 0 53 -14 92 0 -1 1 2 1 -2 1 1 2 -2 2 1 3 -1 1 2 2 -""" -test_data3 = """\ -""" -td_num = 2 +import bisect +import string +import math +import time +import random -def GetTestData(index): -    if index == 1: -        return test_data1 -    if index == 2: -        return test_data2 -    if index == 3: -        return test_data3 +def Golf(): +    (*a,) = map(int, open(0)) -if False: -    with open("../test.txt", mode="w") as f: -        f.write(GetTestData(td_num)) -    with open("../test.txt") as f: -        N, C = list(map(int, f.readline().split())) -        c = [[0 for j in range(C)] for i in range(3)] -        D = [[0 for i in range(C)] for j in range(C)] -        for i in range(C): -            D[i] = [int(x) for x in f.readline().split()] -        for x in range(N): -            y = 0 -            for j in f.readline().split(): -                c[(x + y) % 3][int(j) - 1] += 1 -                y += 1 -else: -    if 0 == 0: -        N, C = list(map(int, input().split())) -        c = [[0 for j in range(C)] for i in range(3)] -        D = [[0 for i in range(C)] for j in range(C)] -        for i in range(C): -            D[i] = [int(x) for x in input().split()] -        for x in range(N): -            y = 0 -            for j in input().split(): -                c[(x + y) % 3][int(j) - 1] += 1 -                y += 1 -St = [[0 for i in range(3)] for j in range(C)] -ans = 10**20 -for c1 in range(C): -    for c2 in range(C): -        for c3 in range(C): -            cc = 0 -            dd = 0 -            for i in range(C): -                cc += c[0][i] * D[i][c1] -                cc += c[1][i] * D[i][c2] -                cc += c[2][i] * D[i][c3] -                dd += c[0][i] * D[c1][i] -                dd += c[1][i] * D[c2][i] -                dd += c[2][i] * D[c3][i] -            if len(set([c1, c2, c3])) == 3: -                ans = min(ans, cc) -            # print(ans,c,D) -# print('N,C=',N,C,'D=',D,'c=',c,'St=',St) +def S_(): +    return input() + + +def IS(): +    return input().split() + + +def LS(): +    return [i for i in input().split()] + + +def I(): +    return int(input()) + + +def MI(): +    return map(int, input().split()) + + +def LI(): +    return [int(i) for i in input().split()] + + +def LI_(): +    return [int(i) - 1 for i in input().split()] + + +def NI(n): +    return [int(input()) for i in range(n)] + + +def NI_(n): +    return [int(input()) - 1 for i in range(n)] + + +def StoI(): +    return [ord(i) - 97 for i in input()] + + +def ItoS(nn): +    return chr(nn + 97) + + +def LtoS(ls): +    return "".join([chr(i + 97) for i in ls]) + + +def GI(V, E, Directed=False, index=0): +    org_inp = [] +    g = [[] for i in range(n)] +    for i in range(E): +        inp = LI() +        org_inp.append(inp) +        if index == 0: +            inp[0] -= 1 +            inp[1] -= 1 +        if len(inp) == 2: +            a, b = inp +            g[a].append(b) +            if not Directed: +                g[b].append(a) +        elif len(inp) == 3: +            a, b, c = inp +            aa = (inp[0], inp[2]) +            bb = (inp[1], inp[2]) +            g[a].append(bb) +            if not Directed: +                g[b].append(aa) +    return g, org_inp + + +def GGI(h, w, search=None, replacement_of_found=".", mp_def={"#": 1, ".": 0}): +    # h,w,g,sg=GGI(h,w,search=['S','G'],replacement_of_found='.',mp_def={'#':1,'.':0}) # sample usage +    mp = [1] * (w + 2) +    found = {} +    for i in range(h): +        s = input() +        for char in search: +            if char in s: +                found[char] = (i + 1) * (w + 2) + s.index(char) + 1 +                mp_def[char] = mp_def[replacement_of_found] +        mp += [1] + [mp_def[j] for j in s] + [1] +    mp += [1] * (w + 2) +    return h + 2, w + 2, mp, found + + +def bit_combination(k, n=2): +    rt = [] +    for tb in range(n**k): +        s = [tb // (n**bt) % n for bt in range(k)] +        rt += [s] +    return rt + + +def show(*inp, end="\n"): +    if show_flg: +        print(*inp, end=end) + + +YN = ["YES", "NO"] +mo = 10**9 + 7 +inf = float("inf") +l_alp = string.ascii_lowercase +u_alp = string.ascii_uppercase +ts = time.time() +# sys.setrecursionlimit(10**7) +input = lambda: sys.stdin.readline().rstrip() + + +def ran_input(): +    import random + +    n = random.randint(4, 16) +    rmin, rmax = 1, 10 +    a = [random.randint(rmin, rmax) for _ in range(n)] +    return n, a + + +show_flg = False +show_flg = True +ans = inf +n, c = LI() +d = [defaultdict(int) for i in " " * 3] +f = [] +for i in range(c): +    f += [LI()] +for i in range(n): +    x = LI() +    for j in range(n): +        d[(i + j) % 3][x[j] - 1] += 1 +for i in range(c): +    for j in range(c): +        for k in range(c): +            if len(set([i, j, k])) < 3: +                continue +            tmp = 0 +            for col, cnt in d[0].items(): +                tmp += f[col][i] * cnt +            for col, cnt in d[1].items(): +                tmp += f[col][j] * cnt +            for col, cnt in d[2].items(): +                tmp += f[col][k] * cnt +            ans = min(ans, tmp)