#include <bits/stdc++.h>
using namespace std;
const int INF = 1000001000;
const long long INFL = 2000000000000001000;
int solve();
int main() {
  srand(2317);
  cout.precision(10);
  cout.setf(ios::fixed);
  int tn = 1;
  for (int i = 0; i < tn; ++i) solve();
}
const int maxn = 21;
string s[maxn];
int a[maxn][maxn];
int d[1 << 20];
int solve() {
  int n, m;
  cin >> n >> m;
  for (int i = 0; i < int(n); ++i) cin >> s[i];
  for (int i = 0; i < int(n); ++i)
    for (int j = 0; j < int(m); ++j) cin >> a[i][j];
  fill(d, d + (1 << n), INF);
  d[0] = 0;
  for (int pos = 0; pos < int(m); ++pos) {
    for (int c = 0; c < int(26); ++c) {
      vector<int> values;
      int mask = 0;
      for (int i = 0; i < int(n); ++i) {
        if (s[i][pos] != char('a' + c)) continue;
        values.push_back(a[i][pos]);
        mask |= (1 << i);
      }
      if (((int)(values).size()) < 2) continue;
      int cost = accumulate(values.begin(), values.end(), 0);
      cost -= *max_element(values.begin(), values.end());
      for (int Q = 0; Q < int(1 << n); ++Q)
        d[Q | mask] = min(d[Q | mask], d[Q] + cost);
    }
  }
  for (int i = 0; i < int(n); ++i) {
    int cost = *min_element(a[i], a[i] + m);
    for (int j = 0; j < int(m); ++j) {
      bool uniq = true;
      for (int k = 0; k < int(n); ++k)
        if (i != k) uniq &= (s[i][j] != s[k][j]);
      if (uniq) cost = 0;
    }
    int mask = (1 << i);
    for (int Q = 0; Q < int(1 << n); ++Q)
      d[Q | mask] = min(d[Q | mask], d[Q] + cost);
  }
  cout << d[(1 << n) - 1] << '\n';
  return 0;
}
