#include <bits/stdc++.h>
using namespace std;
using lli = long long;
using ld = long double;
mt19937 rnd(time(nullptr));
const lli inf = 1e18;
lli Bit(lli mask, lli i) { return (mask >> i) & 1; }
inline void Solve() {
  lli n = 0, m = 0;
  cin >> n >> m;
  vector<string> data(n);
  for (auto &it : data) cin >> it;
  vector<vector<lli>> cost(n, vector<lli>(m));
  for (lli i = 0; i < n; i++) {
    for (lli j = 0; j < m; j++) cin >> cost[i][j];
  }
  vector<vector<pair<lli, lli>>> buffer(n, vector<pair<lli, lli>>(m));
  for (lli i = 0; i < n; i++) {
    for (lli j = 0; j < m; j++) {
      lli mx = 0;
      for (lli k = 0; k < n; k++) {
        if (data[i][j] == data[k][j]) {
          buffer[i][j].first |= (1 << k);
          buffer[i][j].second += cost[k][j];
          mx = max(mx, cost[k][j]);
        }
      }
      buffer[i][j].second -= mx;
    }
  }
  vector<lli> dp((1 << n), inf);
  dp[0] = 0;
  for (lli mask = 0; mask < (1 << n); mask++) {
    if ((dp[mask] == inf) || (mask == (1 << n) - 1)) continue;
    lli id = -1;
    for (lli i = n - 1; i >= 0; i--) {
      if (Bit(mask, i) == 0) {
        id = i;
        break;
      }
    }
    for (lli i = 0; i < m; i++) {
      lli mask1 = buffer[id][i].first, value = buffer[id][i].second;
      dp[mask | mask1] = min(dp[mask | mask1], dp[mask] + value);
      dp[mask | (1 << id)] = min(dp[mask | (1 << id)], dp[mask] + cost[id][i]);
    }
  }
  cout << dp.back();
}
signed main() {
  cout << fixed << setprecision(20);
  Solve();
  return 0;
}
