#include <bits/stdc++.h>
using namespace std;
const int dir[4][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
const int maxn = 25;
const int INF = int(1e9) + 7;
int n, m, male, female;
char Map[maxn][maxn];
struct Node {
  int x, y;
  int speed;
  long long dis[maxn][maxn];
  bool used[maxn][maxn];
  queue<int> quex, quey;
  void read() {
    scanf("%d%d%d", &x, &y, &speed);
    return;
  }
  void pre_bfs() {
    for (int i = 1; i <= n; i++)
      for (int j = 1; j <= m; j++) dis[i][j] = INF, used[i][j] = false;
    while (quex.size()) quex.pop();
    while (quey.size()) quey.pop();
    dis[x][y] = 0;
    used[x][y] = true;
    quex.push(x), quey.push(y);
    while (quex.size()) {
      int a = quex.front(), b = quey.front();
      quex.pop(), quey.pop();
      used[a][b] = false;
      for (int k = 0; k < 4; k++) {
        int nx = a + dir[k][0], ny = b + dir[k][1];
        if (Map[nx][ny] == '#') continue;
        if (nx < 1 || ny < 1 || nx > n || ny > m ||
            dis[nx][ny] <= dis[a][b] + 1)
          continue;
        dis[nx][ny] = dis[a][b] + 1;
        if (!used[nx][ny]) {
          used[nx][ny] = true;
          quex.push(nx), quey.push(ny);
        }
      }
    }
    return;
  }
} node1[maxn * maxn], node2[maxn * maxn];
void read() {
  scanf("%d%d%d%d", &n, &m, &male, &female);
  for (int i = 1; i <= n; i++) scanf("%s", Map[i] + 1);
  Node boss;
  boss.read();
  for (int i = 1; i <= male; i++) node1[i].read();
  for (int i = 1; i <= female; i++) node2[i].read();
  if (male - female == 1)
    node2[++female] = boss;
  else if (female - male == 1)
    node1[++male] = boss;
  else {
    printf("-1\n");
    exit(0);
  }
  return;
}
void init() {
  for (int i = 1; i <= male; i++) node1[i].pre_bfs();
  for (int i = 1; i <= female; i++) node2[i].pre_bfs();
  return;
}
const int maxd = int(1e4) + 7;
const int maxe = int(1e6) + 7;
int tot = 0;
int head[maxd];
int S, T;
struct Edge {
  int from, to, cap, next;
  Edge() {}
  Edge(int x, int y, int c, int nx) : from(x), to(y), cap(c), next(nx) {}
} eage[maxe * 2];
void add(int x, int y, int c) {
  eage[tot] = Edge(x, y, c, head[x]), head[x] = tot++;
  eage[tot] = Edge(y, x, 0, head[y]), head[y] = tot++;
  return;
}
int dis[maxd];
bool used[maxd];
queue<int> que;
bool bfs() {
  for (int i = S; i <= T; i++) dis[i] = INF, used[i] = false;
  while (que.size()) que.pop();
  que.push(S);
  used[S] = true;
  dis[S] = 0;
  while (que.size()) {
    int u = que.front();
    que.pop();
    used[u] = false;
    for (int i = head[u]; ~i; i = eage[i].next)
      if (dis[eage[i].to] > dis[u] + 1 && eage[i].cap) {
        int v = eage[i].to;
        dis[v] = dis[u] + 1;
        if (!used[v]) {
          used[v] = true;
          que.push(v);
        }
      }
  }
  return (dis[T] < INF);
}
int dfs(int u, int flow) {
  if (u == T || !flow) return flow;
  int ret = 0;
  for (int i = head[u]; ~i; i = eage[i].next)
    if (eage[i].cap && dis[eage[i].to] == dis[u] + 1) {
      int v = eage[i].to;
      int newf = dfs(v, min(flow, eage[i].cap));
      eage[i].cap -= newf;
      eage[i ^ 1].cap += newf;
      ret += newf;
      flow -= newf;
      if (!flow) break;
    }
  if (!ret) dis[u] = -1;
  return ret;
}
int dinic() {
  int res = 0;
  while (bfs()) res += dfs(S, INF);
  return res;
}
void build(long long val) {
  S = 1, T = ((((S + male) + female) + (n - 1) * m + m) + (n - 1) * m + m) + 1;
  for (int i = S; i <= T; i++) head[i] = -1;
  tot = 0;
  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= m; j++)
      add((((S + male) + female) + (i - 1) * m + j),
          ((((S + male) + female) + (n - 1) * m + m) + (i - 1) * m + j), 1);
  for (int i = 1; i <= male; i++) {
    add(S, (S + i), 1);
    for (int x = 1; x <= n; x++)
      for (int y = 1; y <= m; y++)
        if (node1[i].dis[x][y] != INF &&
            node1[i].dis[x][y] * node1[i].speed <= val)
          add((S + i), (((S + male) + female) + (x - 1) * m + y), 1);
  }
  for (int i = 1; i <= female; i++) {
    add(((S + male) + i), T, 1);
    for (int x = 1; x <= n; x++)
      for (int y = 1; y <= m; y++)
        if (node2[i].dis[x][y] != INF &&
            node2[i].dis[x][y] * node2[i].speed <= val)
          add(((((S + male) + female) + (n - 1) * m + m) + (x - 1) * m + y),
              ((S + male) + i), 1);
  }
  return;
}
bool check(long long val) {
  build(val);
  return (dinic() == male);
}
int main() {
  read();
  init();
  long long l = 0, r = (1ll << 40), res = -1;
  while (l <= r) {
    long long mid = (l + r) >> 1;
    if (check(mid))
      r = mid - 1, res = mid;
    else
      l = mid + 1;
  }
  printf("%I64d\n", res == INF ? -1 : res);
  return 0;
}
