import std.algorithm;
void main()
{
    import std.stdio, std.string, std.array, std.conv;

    auto buf = readln.chomp.split;
    immutable n = buf[0].to!size_t, c = buf[1].to!size_t;
    int[][] malaise;
    foreach (i; 0..c)
        malaise ~= readln.chomp.split.to!(int[]);
    ubyte[][] board;
    foreach (i; 0..n)
        board ~= readln.chomp.split.to!(ubyte[]);
    foreach (row; board)
        row[] -= 1;
    board.solve(malaise.transpose).writeln;
}

auto solve(in ubyte[][] board, in int[][] malaise)
{
    auto answer = int.max;
    enum size_t m = 3;
    immutable c = malaise.length;
    auto colorCount = new int[][](m, c);
    foreach (i, row; board)
        foreach (j, color; row)
            colorCount[(i+j) % m][color] += 1;
    foreach (color0; 0..c) foreach (color1; 0..c) foreach (color2; 0..c)
    {
        if (color0 == color1) continue;
        if (color0 == color2) continue;
        if (color2 == color1) continue;
        answer = answer.min(colorCount.simulate(malaise[color0], malaise[color1], malaise[color2]));
    }
    return answer;
}

auto simulate(in int[][] count, in int[][] val...)
{
    import std.numeric, std.range;
    int ret = 0;
    foreach (t; count.zip(val))
        ret += dotProduct(t.expand);
    return ret;
}

T[][] transpose(T)(in T[][] x)
{
    auto ret = new T[][](x[0].length, x.length);
    foreach (i, row; x)
        foreach (j, val; row)
            ret[j][i] = val;
    return ret;
}
