#include <bits/stdc++.h>
using namespace std;
inline int toInt(string s) {
  int v;
  istringstream sin(s);
  sin >> v;
  return v;
}
template <class T>
inline string toString(T x) {
  ostringstream sout;
  sout << x;
  return sout.str();
}
int n, m;
int A[30][30];
int DP[1 << 20];
int sum[20][26];
int getMsk[20][26];
int best[20][26];
vector<string> v;
int solve(int msk) {
  if (msk == (1 << n) - 1) return 0;
  int &ret = DP[msk];
  if (ret != -1) return ret;
  ret = 1 << 30;
  for (int i = 0; i < n; ++i) {
    if ((msk | (1 << i)) == msk) continue;
    for (int j = 0; j < m; ++j) {
      ret = min(ret, A[i][j] + solve(msk | (1 << i)));
      int k = v[i][j] - 'a';
      if ((msk | getMsk[j][k]) != msk)
        ret = min(ret, sum[j][k] - best[j][k] + solve(msk | getMsk[j][k]));
    }
    break;
  }
  return ret;
}
int main() {
  {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
  }
  memset(DP, -1, sizeof(DP));
  cin >> n >> m;
  v.resize(n);
  for (int i = 0; i < n; ++i) {
    cin >> v[i];
  }
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < m; ++j) {
      cin >> A[i][j];
      sum[j][v[i][j] - 'a'] += A[i][j];
      getMsk[j][v[i][j] - 'a'] |= (1 << i);
      best[j][v[i][j] - 'a'] = max(best[j][v[i][j] - 'a'], A[i][j]);
    }
  }
  memset(DP, -1, sizeof(DP));
  cout << solve(0);
}
