#include <bits/stdc++.h>
#pragma GCC optimize(2)
#pragma GCC optimize("Ofast", "-funroll-loops", "-fdelete-null-pointer-checks")
#pragma GCC target("ssse3", "sse3", "sse2", "sse", "avx2", "avx")
using namespace std;
const long long inf = 0x7f7f7f7f7f7f;
long long read() {
  long long x = 0, f = 1;
  char c = getchar();
  while (!isdigit(c)) {
    if (c == '-') f = -1;
    c = getchar();
  }
  while (isdigit(c)) {
    x = (x << 3) + (x << 1) + (c ^ 48);
    c = getchar();
  }
  return x * f;
}
const long long N = 23;
const long long M = (1 << N);
long long n, m;
long long dp[M];
long long cross[N][N];
long long w[N][N];
char s[N][N];
long long a[N][N];
inline void check_max(long long &x, long long y) {
  if (x < y) x = y;
}
inline void check_min(long long &x, long long y) {
  if (x > y) x = y;
}
signed main() {
  n = read(), m = read();
  for (long long i = 0; i < n; i++) {
    scanf("%s", s[i]);
  }
  for (long long i = 0; i < n; i++)
    for (long long j = 0; j < m; j++) a[i][j] = read();
  for (long long i = 0; i < n; i++) {
    for (long long j = 0; j < m; j++) {
      long long sum_w = 0, max_wei = -inf;
      for (long long k = 0; k < n; k++) {
        if (s[k][j] == s[i][j]) {
          cross[i][j] |= (1 << k);
          sum_w += a[k][j];
          check_max(max_wei, a[k][j]);
        }
        w[i][j] = sum_w - max_wei;
      }
    }
  }
  long long tmp = (1 << n);
  fill(dp, dp + tmp, inf);
  dp[0] = 0;
  for (long long mask = 0; mask < tmp; mask++) {
    long long i = 0;
    for (; i < n; i++)
      if ((mask & (1 << i)) == 0) break;
    for (long long j = 0; j < m; j++) {
      check_min(dp[mask | (1 << i)], dp[mask] + a[i][j]);
      check_min(dp[mask | cross[i][j]], dp[mask] + w[i][j]);
    }
  }
  printf("%lld", dp[tmp - 1]);
}
