Problem:
Score : 400 points

Problem Statement

There is a grid with N rows and N columns of squares. Let (i,j) be the square at the i-th row from the top and the j-th column from the left.

These squares have to be painted in one of the C colors from Color 1 to Color C. Initially, (i,j) is painted in Color c_{i,j}.

We say the grid is a good grid when the following condition is met for all i,j,x,y satisfying 1 \leq i,j,x,y \leq N:

If (i+j) \% 3=(x+y) \% 3, the color of (i,j) and the color of (x,y) are the same.

If (i+j) \% 3 \neq (x+y) \% 3, the color of (i,j) and the color of (x,y) are different.

Here, X \% Y represents X modulo Y.

We will repaint zero or more squares so that the grid will be a good grid.

For a square, the wrongness when the color of the square is X before repainting and Y after repainting, is D_{X,Y}.

Find the minimum possible sum of the wrongness of all the squares.

Constraints

1 \leq N \leq 500

3 \leq C \leq 30

1 \leq D_{i,j} \leq 1000 (i \neq j),D_{i,j}=0 (i=j)

1 \leq c_{i,j} \leq C

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N C
D_{1,1} ... D_{1,C}
:
D_{C,1} ... D_{C,C}
c_{1,1} ... c_{1,N}
:
c_{N,1} ... c_{N,N}

Output

If the minimum possible sum of the wrongness of all the squares is x, print x.

Sample Input 1

2 3
0 1 1
1 0 1
1 4 0
1 2
3 3

Sample Output 1

3

Repaint (1,1) to Color 2. The wrongness of (1,1) becomes D_{1,2}=1.

Repaint (1,2) to Color 3. The wrongness of (1,2) becomes D_{2,3}=1.

Repaint (2,2) to Color 1. The wrongness of (2,2) becomes D_{3,1}=1.

In this case, the sum of the wrongness of all the squares is 3.

Note that D_{i,j} \neq D_{j,i} is possible.

Sample Input 2

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

Sample Output 2

428

Solution in C# (.NET Core 3.1.201) (judge verdict: Accepted)

using System;
using System.Linq;
using System.Collections.Generic;
using static System.Console;
using System.Text;
using System.IO;
using static System.Math;
using System.Numerics;

namespace AtCoder
{
    public class Program
    {
        public static void Main(string[] args)
        {
            //SetOut(new StreamWriter(OpenStandardOutput()) { AutoFlush = false });
            Solve();
            //Out.Flush();
            Read();
        }

        static void Solve()
        {
            var (N, C) = Slice2<long>();
            var Dij = new long[C][];
            var Cij = new long[N][];
            for (var i = 0; i < C; ++i)
                Dij[i] = Sarray();
            for (var i = 0; i < N; ++i)
                Cij[i] = Sarray();
            var info = Enumerable.Repeat(0, 3).Select(_ => new long[C]).ToArray();
            //それぞれのラインの色情報取得
            for (var i = 0; i < N; ++i)
                for (var j = 0; j < N; ++j)
                {
                    var n = (i + j) % 3;
                    ++info[n][Cij[i][j] - 1];
                }
            var cst = long.MaxValue;
            for (var c0 = 0; c0 < C; ++c0)
            {
                for (var c1 = 0; c1 < C; ++c1)
                {
                    if (c1 == c0) continue;
                    for (var c2 = 0; c2 < C; ++c2)
                    {
                        if (c2 == c1 || c2 == c0) continue;
                        var t = 0L;
                        //各グループをciに塗り替える
                        for (var i = 0; i < C; ++i)
                        {
                            t += info[0][i] * Dij[i][c0];
                            t += info[1][i] * Dij[i][c1];
                            t += info[2][i] * Dij[i][c2];
                        }
                        cst = Min(cst, t);
                    }
                }
            }
            WriteLine(cst);
        }
        static long MAX = long.MaxValue / 2;
        static long[] nums;
        static long dfs(long n)
        {
            if (n < 0) return MAX;
            if (MAX != nums[n]) return nums[n];
            var ret = MAX;
            var nv = 9;
            while (0 <= n - nv) nv *= 9;
            nv /= 9;
            while (nv != 1)
            {
                ret = Min(ret, dfs(n - nv));
                nv /= 9;
            }
            var sv = 6;
            while (0 <= n - sv) sv *= 6;
            nv /= 6;
            while (sv != 1)
            {
                ret = Min(ret, dfs(n - sv));
                sv /= 6;
            }

            ret = Min(ret, dfs(n - 1));
            return nums[n] = ret + 1;
        }

        static long Mod = 998244353;
        static public long[] Sarray() { return ReadLine().Split().Select(long.Parse).ToArray(); }
        static public List<long> Slist() { return ReadLine().Split().Select(long.Parse).ToList(); }
        static public (T1 a, T2 b) Slice<T1, T2>()
        {
            var t = ReadLine().Split();
            return (
            (T1)Convert.ChangeType(t[0], typeof(T1)),
            (T2)Convert.ChangeType(t[1], typeof(T2)));
        }
        static public (T a, T b) Slice2<T>()
        {
            var t = ReadLine().Split();
            return (
            (T)Convert.ChangeType(t[0], typeof(T)),
            (T)Convert.ChangeType(t[1], typeof(T)));
        }
        static public (T a, T b, T c) Slice3<T>()
        {
            var t = ReadLine().Split();
            return (
            (T)Convert.ChangeType(t[0], typeof(T)),
            (T)Convert.ChangeType(t[1], typeof(T)),
            (T)Convert.ChangeType(t[2], typeof(T)));
        }
    }
}