#include <bits/stdc++.h>
using namespace std;
const int N = 23, MXN = N * N * 4;
struct Edge {
  int to, flow;
};
struct Dinic {
  int s, t, P[MXN], D[MXN], qu[MXN];
  vector<int> Adj[MXN];
  vector<Edge> E;
  inline void Add(int v, int u, int w) {
    Adj[v].push_back(E.size());
    E.push_back({u, w});
    Adj[u].push_back(E.size());
    E.push_back({v, 0});
  }
  inline bool BFS() {
    int l = 0, r = 0;
    memset(D, -1, sizeof(D));
    D[s] = 0;
    qu[r++] = s;
    while (r - l) {
      int v = qu[l++];
      for (int &id : Adj[v])
        if (E[id].flow && D[E[id].to] == -1)
          D[E[id].to] = D[v] + 1, qu[r++] = E[id].to;
    }
    return (D[t] != -1);
  }
  int DFS(int v, int flow) {
    if (v == t) return flow;
    int Flow = 0;
    for (int i = P[v]; i < Adj[v].size(); i++) {
      int id = Adj[v][i];
      if (E[id].flow && D[E[id].to] == D[v] + 1) {
        int sub = DFS(E[id].to, min(flow, E[id].flow));
        if (!sub) {
          swap(Adj[v][i], Adj[v][P[v]]);
          P[v]++;
          continue;
        }
        E[id].flow -= sub;
        E[id ^ 1].flow += sub;
        flow -= sub;
        Flow += sub;
        if (!flow) return Flow;
      } else
        swap(Adj[v][i], Adj[v][P[v]]), P[v]++;
    }
    return Flow;
  }
  inline int MaxFlow(int _s, int _t) {
    int Flow = 0;
    s = _s;
    t = _t;
    while (BFS()) {
      memset(P, 0, sizeof(P));
      Flow += DFS(s, INT_MAX);
    }
    return Flow;
  }
};
int n, m, D[N][N], gg[] = {-1, 1, 0, 0};
int fl, ml, X[MXN], Y[MXN], T[MXN];
pair<int, int> qu[MXN];
char S[N][N];
vector<vector<long long> > E;
inline bool Solve(int md) {
  Dinic G;
  int s = ml + fl + n * m * 2, t = s + 1;
  for (int i = 0; i < ml; i++) G.Add(s, i, 1);
  for (int i = 0; i < fl; i++) G.Add(i + ml, t, 1);
  for (int i = 0; i < n; i++)
    for (int j = 0; j < m; j++)
      G.Add(ml + fl + i + j * n, ml + fl + i + j * n + n * m, 1);
  for (int i = 0; i <= md; i++) {
    int id = E[i][1], cell = n * E[i][3] + E[i][2] + ml + fl;
    if (id < ml)
      G.Add(id, cell, 1);
    else
      G.Add(cell + n * m, id, 1);
  }
  return (G.MaxFlow(s, t) == ml);
}
int main() {
  scanf("%d%d%d%d", &n, &m, &ml, &fl);
  if (abs(ml - fl) != 1) return !printf("-1");
  for (int i = 0; i < n; i++) scanf("%s", &S[i]);
  if (ml < fl)
    scanf("%d%d%d", &X[ml], &Y[ml], &T[ml]);
  else
    scanf("%d%d%d", &X[ml + fl], &Y[ml + fl], &T[ml + fl]);
  for (int i = 0; i < ml; i++) scanf("%d%d%d", &X[i], &Y[i], &T[i]);
  if (ml < fl) ml++;
  for (int i = ml; i < ml + fl; i++) scanf("%d%d%d", &X[i], &Y[i], &T[i]);
  if (fl < ml) fl++;
  for (int i = 0; i < ml + fl; i++) {
    int l = 0, r = 0;
    memset(D, -1, sizeof(D));
    X[i]--;
    Y[i]--;
    D[X[i]][Y[i]] = 0;
    qu[r++] = {X[i], Y[i]};
    while (r - l) {
      int a = qu[l].first, b = qu[l++].second;
      E.push_back({1LL * D[a][b] * T[i], i, a, b});
      for (int h = 0; h < 4; h++) {
        int ta = a + gg[h], tb = b + gg[(h + 2) % 4];
        if (ta < 0 || tb < 0 || ta >= n || tb >= m) continue;
        if (S[ta][tb] == '#' || D[ta][tb] != -1) continue;
        D[ta][tb] = D[a][b] + 1;
        qu[r++] = {ta, tb};
      }
    }
  }
  sort(E.begin(), E.end());
  int le = -1, ri = E.size(), md;
  while (ri - le > 1) {
    md = (le + ri) >> 1;
    if (Solve(md))
      ri = md;
    else
      le = md;
  }
  if (ri < E.size()) return !printf("%lld", E[ri][0]);
  return !printf("-1");
}
