#include <bits/stdc++.h>
using namespace std;
template <typename T>
inline void mx(T& x, const T& y) {
  if (x < y) x = y;
}
template <typename T>
inline void mn(T& x, const T& y) {
  if (y < x) x = y;
}
const int di[] = {-1, 0, +1, 0};
const int dj[] = {0, +1, 0, -1};
const int K = 22 * 22;
const int N = 1 + K + K + K + K + 1;
const int M = 2 * (K + K * K + K + K * K + K);
int fieldSize = 0;
int peopleSize = 0;
int nodes;
int edges;
int S;
int T;
int head[N], dhead[N], linke[M], cap[M], dest[M], lvl[N];
int q[N];
inline void addArc(int u, int v, int c) {
  cap[edges] = c;
  dest[edges] = v;
  linke[edges] = head[u];
  head[u] = edges++;
  cap[edges] = 0;
  dest[edges] = u;
  linke[edges] = head[v];
  head[v] = edges++;
}
bool bfs() {
  fill(lvl, lvl + nodes, -1);
  int qh = 0, qt = 0;
  lvl[S] = 0;
  q[qt++] = S;
  while (qh != qt) {
    int u = q[qh++];
    for (int arc = head[u]; arc != -1; arc = linke[arc]) {
      int v = dest[arc];
      if (cap[arc] > 0 && lvl[v] == -1) {
        lvl[v] = lvl[u] + 1;
        q[qt++] = v;
      }
    }
  }
  return lvl[T] != -1;
}
inline int dfs(int u, int f) {
  if (u == T || f == 0) {
    return f;
  }
  for (int& arc = dhead[u]; arc != -1; arc = linke[arc]) {
    int v = dest[arc];
    if (cap[arc] > 0 && lvl[v] == lvl[u] + 1) {
      int pushed = dfs(v, min(f, cap[arc]));
      if (pushed > 0) {
        cap[arc] -= pushed;
        cap[arc ^ 1] += pushed;
        return pushed;
      }
    }
  }
  return 0;
}
inline int maleIndex(int i) { return i; }
inline int fieldInputIndex(int i) { return peopleSize + i; }
inline int fieldOutputIndex(int i) { return peopleSize + fieldSize + i; }
inline int femaleIndex(int i) { return peopleSize + fieldSize + fieldSize + i; }
bool can(const vector<vector<int>>& g, const vector<bool>& good,
         const vector<pair<int, int>>& males,
         const vector<pair<int, int>>& females, const long long& reqTime) {
  fieldSize = g.size();
  peopleSize = males.size();
  S = 2 * (peopleSize + fieldSize);
  T = S + 1;
  nodes = T + 1;
  edges = 0;
  fill(head, head + nodes, -1);
  for (int i = 0; i < (peopleSize); ++i) {
    addArc(S, maleIndex(i), 1);
    int u = males[i].first;
    for (int v = 0; v < (fieldSize); ++v) {
      if (good[v] && g[u][v] < 1000000) {
        long long t = 1LL * males[i].second * g[u][v];
        if (t <= reqTime) {
          addArc(maleIndex(i), fieldInputIndex(v), 1);
        }
      }
    }
  }
  for (int i = 0; i < (fieldSize); ++i) {
    if (good[i]) {
      addArc(fieldInputIndex(i), fieldOutputIndex(i), 1);
    }
  }
  for (int i = 0; i < (peopleSize); ++i) {
    addArc(femaleIndex(i), T, 1);
    int u = females[i].first;
    for (int v = 0; v < (fieldSize); ++v) {
      if (good[v] && g[u][v] < 1000000) {
        long long t = 1LL * females[i].second * g[u][v];
        if (t <= reqTime) {
          addArc(fieldOutputIndex(v), femaleIndex(i), 1);
        }
      }
    }
  }
  int f = 0;
  while (bfs()) {
    copy(head, head + nodes, dhead);
    int pushed;
    while ((pushed = dfs(S, peopleSize)) > 0) {
      f += pushed;
    }
  }
  return f == peopleSize;
}
int main() {
  ios_base::sync_with_stdio(false);
  int n, m, nMales, nFemales;
  cin >> n >> m >> nMales >> nFemales;
  if (abs(nMales - nFemales) != 1) {
    cout << -1 << endl;
    return 0;
  }
  vector<string> a(n);
  for (int i = 0; i < (n); ++i) {
    cin >> a[i];
  }
  vector<vector<int>> g(n * m, vector<int>(n * m, 1000000));
  vector<bool> good(n * m, false);
  for (int i = 0; i < (n); ++i)
    for (int j = 0; j < (m); ++j)
      if (a[i][j] == '.') {
        g[i * m + j][i * m + j] = 0;
        good[i * m + j] = true;
        for (int k = 0; k < (4); ++k) {
          int ii = i + di[k];
          int jj = j + dj[k];
          if (0 <= ii && ii < n && 0 <= jj && j < m && a[ii][jj] == '.') {
            g[i * m + j][ii * m + jj] = 1;
          }
        }
      }
  for (int k = 0; k < (n * m); ++k) {
    for (int i = 0; i < (n * m); ++i) {
      for (int j = 0; j < (n * m); ++j) {
        mn(g[i][j], g[i][k] + g[k][j]);
      }
    }
  }
  auto readPlace = [&] {
    int r, c, t;
    cin >> r >> c >> t;
    --r, --c;
    return make_pair(r * m + c, t);
  };
  vector<pair<int, int>> males;
  vector<pair<int, int>> females;
  ((nMales < nFemales) ? males : females).push_back(readPlace());
  for (int i = 0; i < (nMales); ++i) males.push_back(readPlace());
  for (int i = 0; i < (nFemales); ++i) females.push_back(readPlace());
  int maxDist = 0;
  for (int i = 0; i < (n * m); ++i)
    for (int j = 0; j < (n * m); ++j)
      if (g[i][j] < 1000000) mx(maxDist, g[i][j]);
  long long maxT = 1000000000LL * maxDist;
  long long l = -1;
  long long r = maxT + 1;
  while (r - l > 1) {
    long long m = (l + r) / 2;
    if (can(g, good, males, females, m)) {
      r = m;
    } else {
      l = m;
    }
  }
  if (r == maxT + 1) {
    r = -1;
  }
  cout << r << endl;
  return 0;
}
