#include <bits/stdc++.h>
using namespace std;
const int INF = 1000000000;
template <class T>
int size(T &x) {
  return x.size();
}
int q[3000], d[3000];
struct flow_network {
  struct edge {
    int v, cap, nxt;
    edge() {}
    edge(int _v, int _cap, int _nxt) : v(_v), cap(_cap), nxt(_nxt) {}
  };
  int n, ecnt, *head, *curh;
  vector<edge> e, e_store;
  flow_network(int _n, int m = -1) : n(_n), ecnt(0) {
    e.reserve(2 * (m == -1 ? n : m));
    head = new int[n], curh = new int[n];
    memset(head, -1, n * sizeof(int));
  }
  void destroy() {
    delete[] head;
    delete[] curh;
  }
  void reset() { e = e_store; }
  void add_edge(int u, int v, int uv, int vu = 0) {
    e.push_back(edge(v, uv, head[u]));
    head[u] = ecnt++;
    e.push_back(edge(u, vu, head[v]));
    head[v] = ecnt++;
  }
  int augment(int v, int t, int f) {
    if (v == t) return f;
    for (int &i = curh[v], ret; i != -1; i = e[i].nxt)
      if (e[i].cap > 0 && d[e[i].v] + 1 == d[v])
        if ((ret = augment(e[i].v, t, min(f, e[i].cap))) > 0)
          return (e[i].cap -= ret, e[i ^ 1].cap += ret, ret);
    return 0;
  }
  int max_flow(int s, int t, bool res = true) {
    if (s == t) return 0;
    e_store = e;
    int f = 0, x, l, r;
    while (true) {
      memset(d, -1, n * sizeof(int));
      l = r = 0, d[q[r++] = t] = 0;
      while (l < r)
        for (int v = q[l++], i = head[v]; i != -1; i = e[i].nxt)
          if (e[i ^ 1].cap > 0 && d[e[i].v] == -1)
            d[q[r++] = e[i].v] = d[v] + 1;
      if (d[s] == -1) break;
      memcpy(curh, head, n * sizeof(int));
      while ((x = augment(s, t, INF)) != 0) f += x;
    }
    if (res) reset();
    return f;
  }
};
char arr[30][30];
int dist[30][30][30][30];
vector<pair<pair<int, int>, int> > ppl[3];
pair<pair<int, int>, int> get_person() {
  int x, y, sp;
  scanf("%d %d %d\n", &x, &y, &sp);
  x--, y--;
  return make_pair(pair<int, int>(x, y), sp);
}
int main() {
  int n, m, males, females;
  scanf("%d %d %d %d\n", &n, &m, &males, &females);
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      scanf("%c", &arr[i][j]);
    }
    scanf("\n");
  }
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      for (int k = 0; k < n; k++)
        for (int l = 0; l < m; l++) dist[i][j][k][l] = INF;
      if (arr[i][j] == '#') continue;
      dist[i][j][i][j] = 0;
      queue<pair<int, int> > Q;
      Q.push(pair<int, int>(i, j));
      while (!Q.empty()) {
        pair<int, int> cur = Q.front();
        Q.pop();
        for (int di = -1; di <= 1; di++) {
          for (int dj = -1; dj <= 1; dj++) {
            if ((di == 0) == (dj == 0)) {
              continue;
            }
            pair<int, int> nxt(cur.first + di, cur.second + dj);
            if (nxt.first >= 0 && nxt.first < n && nxt.second >= 0 &&
                nxt.second < m && arr[nxt.first][nxt.second] == '.') {
              if (dist[i][j][nxt.first][nxt.second] == INF) {
                dist[i][j][nxt.first][nxt.second] =
                    1 + dist[i][j][cur.first][cur.second];
                Q.push(nxt);
              }
            }
          }
        }
      }
    }
  }
  pair<pair<int, int>, int> weird = get_person();
  for (int i = 0; i < males; i++) ppl[0].push_back(get_person());
  for (int i = 0; i < females; i++) ppl[1].push_back(get_person());
  if (size(ppl[0]) < size(ppl[1]))
    ppl[0].push_back(weird);
  else
    ppl[1].push_back(weird);
  if (size(ppl[0]) != size(ppl[1])) {
    cout << -1 << endl;
    return 0;
  }
  long long lo = 0, hi = 10000000000000000LL;
  long long res = -1;
  while (lo <= hi) {
    long long mid = lo + (hi - lo) / 2;
    int SOURCE = 0, SINK = 1, MEN = SINK + 1, CELLL = MEN + size(ppl[0]),
        CELLR = CELLL + n * m, WOMEN = CELLR + n * m,
        CNT = WOMEN + size(ppl[1]);
    flow_network g(CNT);
    for (int i = 0; i < size(ppl[0]); i++) {
      g.add_edge(SOURCE, MEN + i, 1);
    }
    for (int i = 0; i < size(ppl[1]); i++) {
      g.add_edge(WOMEN + i, SINK, 1);
    }
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < m; j++) {
        if (arr[i][j] == '.') {
          g.add_edge(CELLL + i * m + j, CELLR + i * m + j, 1);
        }
      }
    }
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < m; j++) {
        for (int k = 0; k < size(ppl[0]); k++) {
          pair<int, int> at = ppl[0][k].first;
          long long spd = ppl[0][k].second;
          if (dist[at.first][at.second][i][j] == INF) continue;
          if (spd * dist[at.first][at.second][i][j] <= mid) {
            g.add_edge(MEN + k, CELLL + i * m + j, 1);
          }
        }
        for (int k = 0; k < size(ppl[1]); k++) {
          pair<int, int> at = ppl[1][k].first;
          long long spd = ppl[1][k].second;
          if (dist[at.first][at.second][i][j] == INF) continue;
          if (spd * dist[at.first][at.second][i][j] <= mid) {
            g.add_edge(CELLR + i * m + j, WOMEN + k, 1);
          }
        }
      }
    }
    if (g.max_flow(SOURCE, SINK) == size(ppl[0])) {
      res = mid;
      hi = mid - 1;
    } else {
      lo = mid + 1;
    }
  }
  cout << res << endl;
  return 0;
}
