unittest
{
	assert( [ "2 3", "0 1 1", "1 0 1", "1 4 0", "1 2", "3 3" ].solve == 3 );
	assert( [ "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" ].solve == 428 );
	
	assert( [ "2 4", "100 100 100 100", "100 0 1 1", "100 1 0 1", "100 1 4 0", "2 3", "4 4" ].solve == 3 );		// 追加ケース
}



import std.algorithm;
import std.conv;
import std.format;
import std.range;
import std.stdio;

void main()
{
	stdin.byLineCopy.solve.writeln;
}

auto solve( Range )( Range input )
if( isInputRange!Range && is( ElementType!Range == string ) )
{
	auto n = 0L;
	auto c = 0L;
	input.front.formattedRead!"%s %s"( n, c );
	auto dss = new long[][]( c, c );
	foreach( ref ds; dss )
	{
		input.popFront;
		ds = input.front.split.to!( long[] );
	}
	auto css = new long[][]( n, n );
	foreach( ref cs; css )
	{
		input.popFront;
		cs = input.front.split.to!( long[] );
		cs[] -= 1;
	}
	
	auto tss = new long[][]( 3, c );
	foreach( x; 0L .. css.length.signed )
	{
		foreach( y; 0L .. css[ x ].length.signed )
		{
			foreach( z; 0L .. c )
			{
				tss[ ( x + y ) % 3 ][ z ] += dss[ css[ x ][ y ] ][ z ];
			}
		}
	}
	
	auto ans = long.max;
	foreach( i; 0L .. c )
	{
		foreach( j; 0L .. c )
		{
			if( i == j ) continue;
			foreach( k; 0L .. c )
			{
				if( i == k || j == k ) continue;
				ans = min( ans, tss[ 0 ][ i ] + tss[ 1 ][ j ] + tss[ 2 ][ k ] );
			}
		}
	}
	return ans;
}
