#include <bits/stdc++.h>
using namespace std;
const long long INF = LLONG_MAX / 2;
const int N = 30;
const int M = 30;
const int A = N * M;
const int B = N * M;
const int S = N * M;
const int V = A + B + S * 2;
const int E = (A + B + A * S + B * S + S) << 1;
int n, m, a, b, xb, yb, vb, mx, size;
int pos[A + B][2], v[A + B];
long long dis[N][M][N][M];
char pic[N][M];
long long ans;
struct network {
  int tov[E], next[E], f[E], v[E], r[E];
  int lab[V], last[V];
  queue<int> q;
  int s, t, tot;
  void insert(int x, int y, int full, int rev) {
    tov[++tot] = y, f[tot] = full, r[tot] = tot + rev, next[tot] = last[x],
    last[x] = tot;
  }
  void addedge(int x, int y, int full) {
    insert(x, y, full, 1), insert(y, x, 0, -1);
  }
  bool relabel() {
    for (int i = s; i <= t; i++) lab[i] = 0;
    for (lab[s] = 1, q.push(s); !q.empty();) {
      int x = q.front();
      q.pop();
      for (int i = last[x], y; i; i = next[i])
        if (!lab[y = tov[i]] && f[i] - v[i]) lab[y] = lab[x] + 1, q.push(y);
    }
    return lab[t];
  }
  int aug(int x, int flow) {
    if (x == t) return flow;
    int ret = 0;
    for (int i = last[x], y; i; i = next[i])
      if (lab[y = tov[i]] == lab[x] + 1 && f[i] - v[i]) {
        int tmp = aug(y, min(flow, f[i] - v[i]));
        if (tmp) {
          ret += tmp, flow -= tmp;
          v[i] += tmp, v[r[i]] -= tmp;
          if (!flow) break;
        } else
          lab[y] = 0;
      }
    return ret;
  }
  int maxflow() {
    int ret = 0, tmp;
    while (relabel()) {
      do {
        ret += tmp = aug(s, INT_MAX);
      } while (tmp);
    }
    return ret;
  }
  void rebuild(long long lim, bool sex) {
    memset(last, 0, sizeof last), memset(next, 0, sizeof next),
        memset(f, 0, sizeof f), memset(v, 0, sizeof v), tot = 0;
    s = 0, t = a + b + size * 2 + 2;
    for (int i = 1; i <= a; i++) addedge(s, i, 1);
    if (sex) addedge(s, a + 1, 1);
    for (int i = 1; i <= b; i++) addedge(i + a + sex + size * 2, t, 1);
    if (!sex) addedge(a + sex + b + size * 2 + 1, t, 1);
    for (int i = 1; i <= size; i++) {
      int x = (i - 1) / m + 1, y = (i - 1) % m + 1;
      for (int j = 1; j <= a; j++)
        if (dis[pos[j][0]][pos[j][1]][x][y] != INF &&
            dis[pos[j][0]][pos[j][1]][x][y] * ::v[j] <= lim)
          addedge(j, a + sex + i * 2 - 1, 1);
      if (sex && dis[xb][yb][x][y] != INF && dis[xb][yb][x][y] * vb <= lim)
        addedge(a + 1, a + sex + i * 2 - 1, 1);
      addedge(a + sex + i * 2 - 1, a + sex + i * 2, 1);
      for (int j = 1; j <= b; j++)
        if (dis[pos[j + a][0]][pos[j + a][1]][x][y] != INF &&
            dis[pos[j + a][0]][pos[j + a][1]][x][y] * ::v[j + a] <= lim)
          addedge(a + sex + i * 2, a + sex + size * 2 + j, 1);
      if (!sex && dis[xb][yb][x][y] != INF && dis[xb][yb][x][y] * vb <= lim)
        addedge(a + sex + i * 2, a + sex + b + 1 + size * 2, 1);
    }
  }
  bool check(int aim) { return maxflow() == aim; }
} net;
queue<pair<int, int> > que;
int di[4][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
void pre() {
  for (int i = 0; i < n; i++)
    for (int j = 0; j < m; j++)
      for (int x = 0; x < n; x++)
        for (int y = 0; y < m; y++) dis[i + 1][j + 1][x + 1][y + 1] = INF;
  mx = 0;
  for (int i = 0; i < n; i++)
    for (int j = 0; j < m; j++)
      if (pic[i][j] == '.') {
        for (dis[i + 1][j + 1][i + 1][j + 1] = 0, que.push(make_pair(i, j));
             !que.empty();) {
          pair<int, int> now = que.front();
          que.pop(),
              mx = max(mx,
                       (int)dis[i + 1][j + 1][now.first + 1][now.second + 1]);
          for (int d = 0, x, y; d < 4; d++) {
            x = now.first + di[d][0], y = now.second + di[d][1];
            if (0 <= x && x < n && 0 <= y && y < m && pic[x][y] == '.' &&
                dis[i + 1][j + 1][x + 1][y + 1] == INF)
              dis[i + 1][j + 1][x + 1][y + 1] =
                  dis[i + 1][j + 1][now.first + 1][now.second + 1] + 1,
                                           que.push(make_pair(x, y));
          }
        }
      }
}
bool check(long long lim) {
  if (a > b)
    return net.rebuild(lim, 0), net.check(a);
  else
    return net.rebuild(lim, 1), net.check(b);
}
void binary_search() {
  pre(), ans = -1;
  if (min(a, b) + 1 != max(a, b)) return;
  long long l = 0, r = 1ll * mx * 1000000000, mid;
  while (l <= r) {
    mid = (l + r) / 2;
    if (check(mid))
      ans = mid, r = mid - 1;
    else
      l = mid + 1;
  }
}
int main() {
  scanf("%d%d%d%d", &n, &m, &a, &b);
  for (int i = 0; i < n; i++) scanf("%s", pic[i]);
  size = n * m;
  scanf("%d%d%d", &xb, &yb, &vb);
  for (int i = 1; i <= a; i++) scanf("%d%d%d", &pos[i][0], &pos[i][1], &v[i]);
  for (int i = 1; i <= b; i++)
    scanf("%d%d%d", &pos[i + a][0], &pos[i + a][1], &v[i + a]);
  binary_search();
  printf("%I64d\n", ans);
  return 0;
}
