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



Sample input:
2 3
0 1 1
1 0 1
1 4 0
1 2
3 3


Sample output:
3

Submission status: Time Limit Exceeded

Solution code:
# input()
# int(input())
# map(int, input().split())
# list(map(int, input().split()))
# list(map(int, list(input()))) # スペースがない数字リストを読み込み
import math
import fractions
import sys
import bisect
import heapq  # 優先度付きキュー(最小値取り出し)
import collections
from collections import Counter
from collections import deque
import pprint

sr = lambda: input()
ir = lambda: int(sr())
lr = lambda: list(map(int, sr().split()))

"""nを素因数分解"""
"""2以上の整数n => [[素因数, 指数], ...]の2次元リスト"""


def factorization(n):
    arr = []
    temp = n
    if n == 1:
        return arr

    for i in range(2, int(-(-n ** 0.5 // 1)) + 1):
        if temp % i == 0:
            cnt = 0
            while temp % i == 0:
                cnt += 1
                temp //= i
            arr.append([i, cnt])

    if temp != 1:
        arr.append([temp, 1])

    if arr == []:
        arr.append([n, 1])

    return arr


# a^n
def power(a, n, mod):
    x = 1
    while n:
        if n & 1:
            x *= a % mod
        n >>= 1
        a *= a % mod
    return x % mod


# n*(n-1)*...*(l+1)*l
def kaijo(n, l, mod):
    if n == 0:
        return 1
    a = n
    tmp = n - 1
    while (tmp >= l):
        a = a * tmp % mod
        tmp -= 1
    return a


inf = 10 ** 18
mod = 10 ** 9 + 7

n,k = lr()
d = [lr() for i in range(k)]
c = [lr() for i in range(n)]
ans = [0 for i in range(3)]
pre = inf
fir = []
sec = []
thr = []
for y in range(n):
    for x in range(n):
        if (y + x) % 3 == 0:
            fir.append(c[y][x]-1)
        elif (y + x) % 3 == 1:
            sec.append(c[y][x]-1)
        else:
            thr.append(c[y][x] - 1)
for i in range(k):
    ans[0] = 0
    for ind in fir:
        ans[0]+=d[ind][i]
    for j in range(k):
        if j!=i:
            ans[1] = 0
            for ind in sec:
                ans[1] += d[ind][j]
            for l in range(k):
                if l != i and l != j:
                    ans[2]=0
                    for ind in thr:
                        ans[2] += d[ind][l]
                    pre = min(pre, sum(ans))
print(pre)

Submission status: Time Limit Exceeded

Solution code:
# input()
# int(input())
# map(int, input().split())
# list(map(int, input().split()))
# list(map(int, list(input()))) # スペースがない数字リストを読み込み
import math
import fractions
import sys
import bisect
import heapq  # 優先度付きキュー(最小値取り出し)
import collections
from collections import Counter
from collections import deque
import pprint

sr = lambda: input()
ir = lambda: int(sr())
lr = lambda: list(map(int, sr().split()))

"""nを素因数分解"""
"""2以上の整数n => [[素因数, 指数], ...]の2次元リスト"""


def factorization(n):
    arr = []
    temp = n
    if n == 1:
        return arr

    for i in range(2, int(-(-n ** 0.5 // 1)) + 1):
        if temp % i == 0:
            cnt = 0
            while temp % i == 0:
                cnt += 1
                temp //= i
            arr.append([i, cnt])

    if temp != 1:
        arr.append([temp, 1])

    if arr == []:
        arr.append([n, 1])

    return arr


# a^n
def power(a, n, mod):
    x = 1
    while n:
        if n & 1:
            x *= a % mod
        n >>= 1
        a *= a % mod
    return x % mod


# n*(n-1)*...*(l+1)*l
def kaijo(n, l, mod):
    if n == 0:
        return 1
    a = n
    tmp = n - 1
    while (tmp >= l):
        a = a * tmp % mod
        tmp -= 1
    return a


inf = 10 ** 18
mod = 10 ** 9 + 7

n,k = lr()
d = [lr() for i in range(k)]
c = [lr() for i in range(n)]
ans = [0 for i in range(3)]
pre = inf
for i in range(k):
    ans[0] = 0
    for y in range(n):
        for x in range(n):
            if (y+x)%3 == 0:
                ans[0]+=d[c[y][x]-1][i]
    for j in range(k):
        if j!=i:
            ans[1] = 0
            for y in range(n):
                for x in range(n):
                    if (y + x) % 3 == 1:
                        ans[1] += d[c[y][x]-1][j]
            for l in range(k):
                if l != i and l != j:
                    ans[2]=0
                    for y in range(n):
                        for x in range(n):
                            if (y + x) % 3 == 2:
                                ans[2] += d[c[y][x]-1][l]
                    pre = min(pre, sum(ans))
print(pre)

Submission status: Time Limit Exceeded

Solution code:
n, c = map(int, input().split())
D = [list(map(int, input().split())) for _ in range(c)]
C = [list(map(int, input().split())) for _ in range(n)]

for i, l in enumerate(C):
    l = [x-1 for x in l]
    C[i] = l

import itertools
ans = 10**18
for p in itertools.permutations(range(c), 3):
    temp = 0
    for i in range(n):
        for j in range(n):
            x = C[i][j]
            y = p[(i+j)%3]
            temp += D[x][y]
    ans = min(temp, ans)
print(ans)

Submission status: Time Limit Exceeded

Solution code:
from sys import stdin
def main():
    #入力
    readline=stdin.readline
    n,max_c=map(int,readline().split())
    d=[list(map(int,readline().split())) for _ in range(max_c)]
    c=[list(map(lambda x:int(x)-1,readline().split())) for _ in range(n)]

    #前処理
    color_table=[[0]*max_c for _ in range(3)]
    for color in range(max_c):
        for i in range(n):
            for j in range(n):
                color_table[(i+j+2)%3][color]+=d[c[i][j]][color]

    #全探索
    ans=float("inf")
    for i in range(max_c):
        for j in range(max_c):
            for k in range(max_c):
                if i==j or j==k or k==i:
                    continue
                ans=min(ans,color_table[0][i]+color_table[1][j]+color_table[2][k])

    print(ans)

if __name__=="__main__":
    main()

Submission status: Time Limit Exceeded

Solution code:
# coding: utf-8
import sys
from itertools import permutations

sr = lambda: sys.stdin.readline().rstrip()
ir = lambda: int(sr())
lr = lambda: list(map(int, sr().split()))

# 3色を全探索
N, COLOR = lr()
D = [lr() for _ in range(COLOR)]
C = [lr() for _ in range(N)]

answer = 10 ** 10
for comb in permutations(range(COLOR), 3):
    temp = 0
    for i in range(N):
        for j in range(N):
            num = (i+j)%3
            color = comb[num]
            temp += D[C[i][j]-1][color]
    if temp < answer:
        answer = temp

print(answer)
# 15

Submission status: Time Limit Exceeded

Solution code:
n,C = map(int,input().split())
d = [[int(i) for i in input().split()] for _ in range(C)]
c = [[int(i)-1 for i in input().split()] for _ in range(n)]

cnt0 = [0]*C
cnt1 = [0]*C
cnt2 = [0]*C
for i in range(n):
    for j in range(n):
        for k in range(C):
            if (i+j)%3 == 0: cnt0[k] += d[c[i][j]][k]
            elif (i+j)%3 == 1: cnt1[k] += d[c[i][j]][k]
            else: cnt2[k] += d[c[i][j]][k]

ans = float("inf")
for i in range(C):
    for j in range(C):
        if i == j: continue
        for k in range(C):
            if i == k or j == k: continue
            ans = min(ans, cnt0[i] + cnt1[j] + cnt2[k])
print(ans)

Submission status: Time Limit Exceeded

Solution code:
n, c = map(int, input().split())
D = [tuple(map(int, input().split())) for _ in range(c)]
C = [tuple(map(lambda x:int(x)-1, input().split())) for _ in range(n)]

# 全ての色について違和感を記録
dst = [[0, 0, 0] for _ in range(c)]
for ci in range(c):
    for i in range(n):
        for j in range(n):
            c_from = C[i][j]
            dst[ci][(i+j)%3] += D[c_from][ci]

from itertools import permutations
d = 1000*500*500
for p0, p1, p2 in permutations(list(range(c)), 3):
    d = min(d, dst[p0][0] + dst[p1][1] + dst[p2][2])
print(d)

Submission status: Time Limit Exceeded

Solution code:
n, c = map(int, input().split())
D = [tuple(map(int, input().split())) for _ in range(c)]
C = [tuple(map(lambda x:int(x)-1, input().split())) for _ in range(n)]

grid = [[(i+j)% 3 for i in range(n)] for j in range(n)]

# 全ての色について違和感を記録
dst = [[0, 0, 0] for _ in range(c)]
for ci in range(c):
    for i in range(n):
        for j in range(n):
            c_from = C[i][j]
            dst[ci][grid[i][j]] += D[c_from][ci]

from itertools import permutations
d = 1000*500*500
for p0, p1, p2 in permutations(list(range(c)), 3):
    d = min(d, dst[p0][0] + dst[p1][1] + dst[p2][2])
print(d)

Submission status: Time Limit Exceeded

Solution code:
n, c = map(int, input().split())
D = [tuple(map(int, input().split())) for _ in range(c)]
C = [tuple(map(lambda x:int(x)-1, input().split())) for _ in range(n)]

grid = [[(i+j)% 3 for i in range(n)] for j in range(n)]

mind = 1000*500*500
from itertools import permutations
for p in permutations(list(range(c)), 3):
    sumd = 0
    for i in range(n):
        for j in range(n):
            c_to = p[grid[i][j]]
            c_from = C[i][j]
            sumd += D[c_from][c_to]
        if sumd > mind:
            break
    else:
        mind = sumd

print(mind)

Submission status: Time Limit Exceeded

Solution code:
import sys
from itertools import permutations
N, C = map(int, sys.stdin.readline().rstrip().split())

d = []
for _ in range(C):
    d.append(tuple(map(int, sys.stdin.readline().rstrip().split())))

r_0 = []
r_1 = []
r_2 = []
for i in range(N):
    g = list(map(int, sys.stdin.readline().rstrip().split()))
    for j in range(N):
        if (i + j + 2) % 3 == 0:
            r_0.append(g[j])
        elif (i + j + 2) % 3 == 1:
            r_1.append(g[j])
        else:
            r_2.append(g[j])

ans = 10**18
for c_1, c_2, c_3 in permutations(range(1, C + 1), 3):
    total = 0
    for r in r_0:
        total += d[r - 1][c_1 - 1]
    for r in r_1:
        total += d[r - 1][c_2 - 1]
    for r in r_2:
        total += d[r - 1][c_3 - 1]
    ans = min(ans, total)
print(ans)

Submission status: Time Limit Exceeded

Solution code:
#!/usr/bin/env python3

import sys
# import time
# import math
# import numpy as np
# import scipy.sparse.csgraph as cs            # csgraph_from_dense(ndarray, null_value=inf), bellman_ford(G, return_predecessors=True), dijkstra, floyd_warshall
# import random                                # random, uniform, randint, randrange, shuffle, sample
# import string                                # ascii_lowercase, ascii_uppercase, ascii_letters, digits, hexdigits
# import re                                    # re.compile(pattern) => ptn obj; p.search(s), p.match(s), p.finditer(s) => match obj; p.sub(after, s)
# from bisect import bisect_left, bisect_right # bisect_left(a, x, lo=0, hi=len(a)) returns i such that all(val<x for val in a[lo:i]) and all(val>-=x for val in a[i:hi]).
# from collections import deque                # deque class. deque(L): dq.append(x), dq.appendleft(x), dq.pop(), dq.popleft(), dq.rotate()
# from collections import defaultdict          # subclass of dict. defaultdict(facroty)
# from collections import Counter              # subclass of dict. Counter(iter): c.elements(), c.most_common(n), c.subtract(iter)
# from datetime import date, datetime          # date.today(), date(year,month,day) => date obj; datetime.now(), datetime(year,month,day,hour,second,microsecond) => datetime obj; subtraction => timedelta obj
# from datetime.datetime import strptime       # strptime('2019/01/01 10:05:20', '%Y/%m/%d/ %H:%M:%S') returns datetime obj
# from datetime import timedelta               # td.days, td.seconds, td.microseconds, td.total_seconds(). abs function is also available.
# from copy import copy, deepcopy              # use deepcopy to copy multi-dimentional matrix without reference
# from functools import reduce                 # reduce(f, iter[, init])
# from functools import lru_cache              # @lrucache ...arguments of functions should be able to be keys of dict (e.g. list is not allowed)
# from heapq import heapify, heappush, heappop # built-in list. heapify(L) changes list in-place to min-heap in O(n), heappush(heapL, x) and heappop(heapL) in O(lgn).
# from heapq import nlargest, nsmallest        # nlargest(n, iter[, key]) returns k-largest-list in O(n+klgn).
# from itertools import count, cycle, repeat   # count(start[,step]), cycle(iter), repeat(elm[,n])
# from itertools import groupby                # [(k, list(g)) for k, g in groupby('000112')] returns [('0',['0','0','0']), ('1',['1','1']), ('2',['2'])]
# from itertools import starmap                # starmap(pow, [[2,5], [3,2]]) returns [32, 9]
from itertools import product, permutations  # product(iter, repeat=n), permutations(iter[,r])
# from itertools import combinations, combinations_with_replacement
# from itertools import accumulate             # accumulate(iter[, f])
# from operator import itemgetter              # itemgetter(1), itemgetter('key')
# from fractions import gcd                    # for Python 3.4 (previous contest @AtCoder)



def main():
    mod = 1000000007                # 10^9+7
    inf = float('inf')              # sys.float_info.max = 1.79...e+308
    # inf = 2 ** 64 - 1             # (for fast JIT compile in PyPy) 1.84...e+19
    sys.setrecursionlimit(10**6)    # 1000 -> 1000000
    def input(): return sys.stdin.readline().rstrip()
    def ii():    return int(input())
    def mi():    return map(int, input().split())
    def mi_0():  return map(lambda x: int(x)-1, input().split())
    def lmi():   return list(map(int, input().split()))
    def lmi_0(): return list(map(lambda x: int(x)-1, input().split()))
    def li():    return list(input())

    
    n, c = mi()
    color_cost = [lmi() for _ in range(c)]    # color x -> color y (0 to c-1 表現) にかかる擦ろtは color_cost[x][y]
    group = [[] for _ in range(3)]    # 0-index で i+j%3=0, 1, 2 となるやつら
    for i in range(n):
        tmp = lmi_0()    # color を 0 to c-1 表現に
        # print(tmp)
        for j in range(n):
            group[(i+j)%3].append(tmp[j])
    
    zero, one, two = group
    # print(zero)
    # print(one)
    # print(two)

    ans = 10**15
    for color_zero, color_one, color_two in permutations(range(c), r=3):
        cost = 0
        for col in zero:
            cost += color_cost[col][color_zero]
        if cost >= ans:    # 定数倍高速化
            continue        
        for col in one:
            cost += color_cost[col][color_one]
        if cost >= ans:
            continue
        for col in two:
            cost += color_cost[col][color_two]
        ans = min(ans, cost)
    print(ans)



if __name__ == "__main__":
    main()

"""
O(10^7) だけど通らないっぽい
"""

Submission status: Time Limit Exceeded

Solution code:
#!/usr/bin/env python3

import sys
# import time
# import math
# import numpy as np
# import scipy.sparse.csgraph as cs            # csgraph_from_dense(ndarray, null_value=inf), bellman_ford(G, return_predecessors=True), dijkstra, floyd_warshall
# import random                                # random, uniform, randint, randrange, shuffle, sample
# import string                                # ascii_lowercase, ascii_uppercase, ascii_letters, digits, hexdigits
# import re                                    # re.compile(pattern) => ptn obj; p.search(s), p.match(s), p.finditer(s) => match obj; p.sub(after, s)
# from bisect import bisect_left, bisect_right # bisect_left(a, x, lo=0, hi=len(a)) returns i such that all(val<x for val in a[lo:i]) and all(val>-=x for val in a[i:hi]).
# from collections import deque                # deque class. deque(L): dq.append(x), dq.appendleft(x), dq.pop(), dq.popleft(), dq.rotate()
# from collections import defaultdict          # subclass of dict. defaultdict(facroty)
# from collections import Counter              # subclass of dict. Counter(iter): c.elements(), c.most_common(n), c.subtract(iter)
# from datetime import date, datetime          # date.today(), date(year,month,day) => date obj; datetime.now(), datetime(year,month,day,hour,second,microsecond) => datetime obj; subtraction => timedelta obj
# from datetime.datetime import strptime       # strptime('2019/01/01 10:05:20', '%Y/%m/%d/ %H:%M:%S') returns datetime obj
# from datetime import timedelta               # td.days, td.seconds, td.microseconds, td.total_seconds(). abs function is also available.
# from copy import copy, deepcopy              # use deepcopy to copy multi-dimentional matrix without reference
# from functools import reduce                 # reduce(f, iter[, init])
# from functools import lru_cache              # @lrucache ...arguments of functions should be able to be keys of dict (e.g. list is not allowed)
# from heapq import heapify, heappush, heappop # built-in list. heapify(L) changes list in-place to min-heap in O(n), heappush(heapL, x) and heappop(heapL) in O(lgn).
# from heapq import nlargest, nsmallest        # nlargest(n, iter[, key]) returns k-largest-list in O(n+klgn).
# from itertools import count, cycle, repeat   # count(start[,step]), cycle(iter), repeat(elm[,n])
# from itertools import groupby                # [(k, list(g)) for k, g in groupby('000112')] returns [('0',['0','0','0']), ('1',['1','1']), ('2',['2'])]
# from itertools import starmap                # starmap(pow, [[2,5], [3,2]]) returns [32, 9]
from itertools import product, permutations  # product(iter, repeat=n), permutations(iter[,r])
# from itertools import combinations, combinations_with_replacement
# from itertools import accumulate             # accumulate(iter[, f])
# from operator import itemgetter              # itemgetter(1), itemgetter('key')
# from fractions import gcd                    # for Python 3.4 (previous contest @AtCoder)



def main():
    mod = 1000000007                # 10^9+7
    inf = float('inf')              # sys.float_info.max = 1.79...e+308
    # inf = 2 ** 64 - 1             # (for fast JIT compile in PyPy) 1.84...e+19
    sys.setrecursionlimit(10**6)    # 1000 -> 1000000
    def input(): return sys.stdin.readline().rstrip()
    def ii():    return int(input())
    def mi():    return map(int, input().split())
    def mi_0():  return map(lambda x: int(x)-1, input().split())
    def lmi():   return list(map(int, input().split()))
    def lmi_0(): return list(map(lambda x: int(x)-1, input().split()))
    def li():    return list(input())


    def calc_cost(zero, one, two, color_cost, color_pattern):
        cost = 0
        color_zero, color_one, color_two = color_pattern
        for col in zero:
            cost += color_cost[col][color_zero]
        for col in one:
            cost += color_cost[col][color_one]
        for col in two:
            cost += color_cost[col][color_two]    
        return cost
    
    
    n, c = mi()
    color_cost = [lmi() for _ in range(c)]    # color x -> color y (0 to c-1 表現) にかかる擦ろtは color_cost[x][y]
    group = [[] for _ in range(3)]    # 0-index で i+j%3=0, 1, 2 となるやつら
    for i in range(n):
        tmp = lmi_0()    # color を 0 to c-1 表現に
        # print(tmp)
        for j in range(n):
            group[(i+j)%3].append(tmp[j])
    
    zero, one, two = group
    # print(zero)
    # print(one)
    # print(two)

    ans = 10**15
    for color_pattern in permutations(range(c), r=3):
        ans = min(ans, calc_cost(zero, one, two, color_cost, color_pattern))
    print(ans)



if __name__ == "__main__":
    main()

"""
O(10^7) だけど通らないっぽい
"""

Submission status: Time Limit Exceeded

Solution code:
#!/usr/bin/env python3

import sys
# import time
# import math
import numpy as np
# import scipy.sparse.csgraph as cs            # csgraph_from_dense(ndarray, null_value=inf), bellman_ford(G, return_predecessors=True), dijkstra, floyd_warshall
# import random                                # random, uniform, randint, randrange, shuffle, sample
# import string                                # ascii_lowercase, ascii_uppercase, ascii_letters, digits, hexdigits
# import re                                    # re.compile(pattern) => ptn obj; p.search(s), p.match(s), p.finditer(s) => match obj; p.sub(after, s)
# from bisect import bisect_left, bisect_right # bisect_left(a, x, lo=0, hi=len(a)) returns i such that all(val<x for val in a[lo:i]) and all(val>-=x for val in a[i:hi]).
# from collections import deque                # deque class. deque(L): dq.append(x), dq.appendleft(x), dq.pop(), dq.popleft(), dq.rotate()
# from collections import defaultdict          # subclass of dict. defaultdict(facroty)
# from collections import Counter              # subclass of dict. Counter(iter): c.elements(), c.most_common(n), c.subtract(iter)
# from datetime import date, datetime          # date.today(), date(year,month,day) => date obj; datetime.now(), datetime(year,month,day,hour,second,microsecond) => datetime obj; subtraction => timedelta obj
# from datetime.datetime import strptime       # strptime('2019/01/01 10:05:20', '%Y/%m/%d/ %H:%M:%S') returns datetime obj
# from datetime import timedelta               # td.days, td.seconds, td.microseconds, td.total_seconds(). abs function is also available.
# from copy import copy, deepcopy              # use deepcopy to copy multi-dimentional matrix without reference
# from functools import reduce                 # reduce(f, iter[, init])
# from functools import lru_cache              # @lrucache ...arguments of functions should be able to be keys of dict (e.g. list is not allowed)
# from heapq import heapify, heappush, heappop # built-in list. heapify(L) changes list in-place to min-heap in O(n), heappush(heapL, x) and heappop(heapL) in O(lgn).
# from heapq import nlargest, nsmallest        # nlargest(n, iter[, key]) returns k-largest-list in O(n+klgn).
# from itertools import count, cycle, repeat   # count(start[,step]), cycle(iter), repeat(elm[,n])
# from itertools import groupby                # [(k, list(g)) for k, g in groupby('000112')] returns [('0',['0','0','0']), ('1',['1','1']), ('2',['2'])]
# from itertools import starmap                # starmap(pow, [[2,5], [3,2]]) returns [32, 9]
from itertools import product, permutations  # product(iter, repeat=n), permutations(iter[,r])
# from itertools import combinations, combinations_with_replacement
# from itertools import accumulate             # accumulate(iter[, f])
# from operator import itemgetter              # itemgetter(1), itemgetter('key')
# from fractions import gcd                    # for Python 3.4 (previous contest @AtCoder)



def main():
    mod = 1000000007                # 10^9+7
    inf = float('inf')              # sys.float_info.max = 1.79...e+308
    # inf = 2 ** 64 - 1             # (for fast JIT compile in PyPy) 1.84...e+19
    sys.setrecursionlimit(10**6)    # 1000 -> 1000000
    def input(): return sys.stdin.readline().rstrip()
    def ii():    return int(input())
    def mi():    return map(int, input().split())
    def mi_0():  return map(lambda x: int(x)-1, input().split())
    def lmi():   return list(map(int, input().split()))
    def lmi_0(): return list(map(lambda x: int(x)-1, input().split()))
    def li():    return list(input())


    def calc_cost(ndarr1, ndarr2):
        cost = 0
        for col in ndarr1:
            cost += ndarr2[col]
        return cost
    
    
    n, c = mi()
    color_cost = [lmi() for _ in range(c)]    # color x -> color y (0 to c-1 表現) にかかる擦ろtは color_cost[x][y]
    color_cost = np.array(color_cost)

    group = [[] for _ in range(3)]    # 0-index で i+j%3=0, 1, 2 となるやつら
    for i in range(n):
        tmp = lmi_0()    # color を 0 to c-1 表現に
        # print(tmp)
        for j in range(n):
            group[(i+j)%3].append(tmp[j])
    
    zero, one, two = map(lambda x: np.array(x), group)
    # print(zero)
    # print(one)
    # print(two)

    ans = inf
    for color_pattern in permutations(range(c), r=3):
        ans = min(ans, calc_cost(zero, color_cost[:, color_pattern[0]]) + calc_cost(one, color_cost[:, color_pattern[1]]) + calc_cost(two, color_cost[:, color_pattern[2]]))
    
    print(ans)


if __name__ == "__main__":
    main()

Submission status: Time Limit Exceeded

Solution code:
#!/usr/bin/env python3

import sys
# import time
# import math
# import numpy as np
# import scipy.sparse.csgraph as cs            # csgraph_from_dense(ndarray, null_value=inf), bellman_ford(G, return_predecessors=True), dijkstra, floyd_warshall
# import random                                # random, uniform, randint, randrange, shuffle, sample
# import string                                # ascii_lowercase, ascii_uppercase, ascii_letters, digits, hexdigits
# import re                                    # re.compile(pattern) => ptn obj; p.search(s), p.match(s), p.finditer(s) => match obj; p.sub(after, s)
# from bisect import bisect_left, bisect_right # bisect_left(a, x, lo=0, hi=len(a)) returns i such that all(val<x for val in a[lo:i]) and all(val>-=x for val in a[i:hi]).
# from collections import deque                # deque class. deque(L): dq.append(x), dq.appendleft(x), dq.pop(), dq.popleft(), dq.rotate()
# from collections import defaultdict          # subclass of dict. defaultdict(facroty)
# from collections import Counter              # subclass of dict. Counter(iter): c.elements(), c.most_common(n), c.subtract(iter)
# from datetime import date, datetime          # date.today(), date(year,month,day) => date obj; datetime.now(), datetime(year,month,day,hour,second,microsecond) => datetime obj; subtraction => timedelta obj
# from datetime.datetime import strptime       # strptime('2019/01/01 10:05:20', '%Y/%m/%d/ %H:%M:%S') returns datetime obj
# from datetime import timedelta               # td.days, td.seconds, td.microseconds, td.total_seconds(). abs function is also available.
# from copy import copy, deepcopy              # use deepcopy to copy multi-dimentional matrix without reference
# from functools import reduce                 # reduce(f, iter[, init])
# from functools import lru_cache              # @lrucache ...arguments of functions should be able to be keys of dict (e.g. list is not allowed)
# from heapq import heapify, heappush, heappop # built-in list. heapify(L) changes list in-place to min-heap in O(n), heappush(heapL, x) and heappop(heapL) in O(lgn).
# from heapq import nlargest, nsmallest        # nlargest(n, iter[, key]) returns k-largest-list in O(n+klgn).
# from itertools import count, cycle, repeat   # count(start[,step]), cycle(iter), repeat(elm[,n])
# from itertools import groupby                # [(k, list(g)) for k, g in groupby('000112')] returns [('0',['0','0','0']), ('1',['1','1']), ('2',['2'])]
# from itertools import starmap                # starmap(pow, [[2,5], [3,2]]) returns [32, 9]
from itertools import product, permutations  # product(iter, repeat=n), permutations(iter[,r])
# from itertools import combinations, combinations_with_replacement
# from itertools import accumulate             # accumulate(iter[, f])
# from operator import itemgetter              # itemgetter(1), itemgetter('key')
# from fractions import gcd                    # for Python 3.4 (previous contest @AtCoder)



def main():
    mod = 1000000007                # 10^9+7
    inf = float('inf')              # sys.float_info.max = 1.79...e+308
    # inf = 2 ** 64 - 1             # (for fast JIT compile in PyPy) 1.84...e+19
    sys.setrecursionlimit(10**6)    # 1000 -> 1000000
    def input(): return sys.stdin.readline().rstrip()
    def ii():    return int(input())
    def mi():    return map(int, input().split())
    def mi_0():  return map(lambda x: int(x)-1, input().split())
    def lmi():   return list(map(int, input().split()))
    def lmi_0(): return list(map(lambda x: int(x)-1, input().split()))
    def li():    return list(input())


    def calc_cost(zero, one, two, color_cost, color_pattern):
        cost = 0
        color_zero, color_one, color_two = color_pattern
        for (i, j), col in zero:
            cost += color_cost[col][color_zero]
        for (i, j), col in one:
            cost += color_cost[col][color_one]
        for (i, j), col in two:
            cost += color_cost[col][color_two]    
        return cost
    
    
    n, c = mi()
    color_cost = [lmi() for _ in range(c)]    # color x -> color y (0 to c-1 表現) にかかる擦ろtは color_cost[x][y]
    group = [[] for _ in range(3)]    # 0-index で i+j%3=0, 1, 2 となるやつら
    for i in range(n):
        tmp = lmi_0()    # color を 0 to c-1 表現に
        # print(tmp)
        for j in range(n):
            group[(i+j)%3].append(((i, j), tmp[j]))
    
    zero, one, two = group
    # print(zero)
    # print(one)
    # print(two)

    ans = inf
    for color_pattern in permutations(range(c), r=3):
        ans = min(ans, calc_cost(zero, one, two, color_cost, color_pattern))
    print(ans)



if __name__ == "__main__":
    main()

Submission status: Time Limit Exceeded

Solution code:
import sys
input = sys.stdin.buffer.readline

def main():
    n, c = map(int, input().split())
    D = [list(map(int, input().split())) for _ in range(c)]
    C_ = [list(map(int, input().split())) for _ in range(n)]
    C = [0]*n
    for i, c_ in enumerate(C_):
        c_ = [x-1 for x in c_]
        C[i] = c_

    #print(C)
    L = [[0]*c for _ in range(3)]
    for k in range(c):
        for i in range(n):
            for j in range(n):
                m = (i+j)%3
                x = C[i][j]
                L[m][k] += D[x][k]
                
    X = [[] for _ in range(3)]
    for j in range(3):
        for i, x in enumerate(L[j]):
            X[j].append((x, i))
    for i, x in enumerate(X):
        x.sort()
        x = x[0:3]
        X[i] = x

    #print(X)
    import itertools
    ans = 10**18
    for p in itertools.product(range(3), repeat=3):
        used_col = set()
        temp = 0
        for j in range(3):
            x, i =X[j][p[j]]
            if i in used_col:
                break
            else:
                temp += x
                used_col.add(i)
        else:
            ans = min(temp, ans)
    print(ans)

if __name__ == '__main__':
    main()