#include <bits/stdc++.h>
using namespace std;
const double EPS = -1e8;
const double Pi = acos(-1);
bool inline equ(double a, double b) { return fabs(a - b) < EPS; }
struct Maxflow {
  static const int MAXV = 20010;
  static const int INF = 1000000;
  struct Edge {
    int v, c, r;
    Edge(int _v, int _c, int _r) : v(_v), c(_c), r(_r) {}
  };
  int s, t;
  vector<Edge> G[MAXV * 2];
  int iter[MAXV * 2], d[MAXV * 2], gap[MAXV * 2], tot;
  void flowinit(int x) {
    tot = x + 2;
    s = x + 1, t = x + 2;
    for (int i = 0; i <= tot; i++) {
      G[i].clear();
      iter[i] = d[i] = gap[i] = 0;
    }
  }
  void addEdge(int u, int v, int c) {
    G[u].push_back(Edge(v, c, (int)(G[v]).size()));
    G[v].push_back(Edge(u, 0, (int)(G[u]).size() - 1));
  }
  int dfs(int p, int flow) {
    if (p == t) return flow;
    for (int &i = iter[p]; i < (int)(G[p]).size(); i++) {
      Edge &e = G[p][i];
      if (e.c > 0 && d[p] == d[e.v] + 1) {
        int f = dfs(e.v, min(flow, e.c));
        if (f) {
          e.c -= f;
          G[e.v][e.r].c += f;
          return f;
        }
      }
    }
    if ((--gap[d[p]]) == 0)
      d[s] = tot;
    else {
      d[p]++;
      iter[p] = 0;
      ++gap[d[p]];
    }
    return 0;
  }
  int maxflow() {
    int res = 0;
    gap[0] = tot;
    for (res = 0; d[s] < tot; res += dfs(s, INF))
      ;
    return res;
  }
} flow;
void fail() {
  cout << "-1\n";
  exit(0);
}
const int MAXN = 25;
int dx[] = {0, 1, 0, -1};
int dy[] = {1, 0, -1, 0};
struct XD {
  int x, y;
  long long t;
  void input() { cin >> x >> y >> t; }
};
int n, m, ma, fe, k;
char in[MAXN][MAXN];
XD a[MAXN * MAXN], b[MAXN * MAXN];
tuple<int, int> qu[1000000];
inline void expand(XD x, int id, long long T, bool flag) {
  static long long dis[MAXN][MAXN];
  static bool vis[MAXN][MAXN];
  static auto ok = [&](int tx, int ty) {
    return 1 <= tx && tx <= n && 1 <= ty && ty <= m && in[tx][ty] == '.' &&
           !vis[tx][ty];
  };
  long long inc = x.t;
  for (int i = (1); i <= (n); i++) fill(vis[i] + 1, vis[i] + m + 1, 0);
  int ql = 0, qr = 0;
  qu[qr++] = tuple<int, int>(x.x, x.y);
  vis[x.x][x.y] = 1;
  dis[x.x][x.y] = 0;
  while (ql < qr) {
    int px, py;
    tie(px, py) = qu[ql++];
    if (dis[px][py] > T) continue;
    if (!flag)
      flow.addEdge(id, k + m * (px - 1) + py, 1);
    else
      flow.addEdge(k + n * m + m * (px - 1) + py, id, 1);
    for (int i = (0); i <= (3); i++) {
      int tx, ty;
      tie(tx, ty) = tuple<int, int>(px + dx[i], py + dy[i]);
      if (!ok(tx, ty)) continue;
      vis[tx][ty] = 1;
      dis[tx][ty] = dis[px][py] + inc;
      qu[qr++] = tuple<int, int>(tx, ty);
    }
  }
}
inline bool ok(long long T) {
  flow.flowinit(n * m + n * m + k + k);
  for (int i = (1); i <= (k); i++) flow.addEdge(flow.s, i, 1);
  for (int i = (1); i <= (k); i++)
    flow.addEdge(k + n * m + n * m + i, flow.t, 1);
  for (int i = (1); i <= (n); i++)
    for (int j = (1); j <= (m); j++)
      flow.addEdge(k + m * (i - 1) + j, k + n * m + m * (i - 1) + j, 1);
  for (int i = (1); i <= (k); i++) expand(a[i], i, T, 0);
  for (int i = (1); i <= (k); i++) expand(b[i], k + n * m + n * m + i, T, 1);
  return flow.maxflow() == k;
}
int main() {
  ios_base::sync_with_stdio(0);
  cin >> n >> m >> ma >> fe;
  for (int i = (1); i <= (n); i++) cin >> (in[i] + 1);
  if (1 + ma == fe)
    a[1 + ma].input();
  else if (ma == 1 + fe)
    b[1 + fe].input();
  else
    fail();
  for (int i = (1); i <= (ma); i++) a[i].input();
  for (int i = (1); i <= (fe); i++) b[i].input();
  k = max(ma, fe);
  long long lb = 0ll, ub = 1000000000000ll, ans = -1ll;
  while (lb <= ub) {
    long long mid = (lb + ub) / 2ll;
    if (ok(mid)) {
      ub = mid - 1ll;
      ans = mid;
    } else
      lb = mid + 1ll;
  }
  cout << ans << '\n';
}
