#include <bits/stdc++.h>
using namespace std;
vector<int> disp[500][500];
int n, m, a, b;
const int pos[4][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
class edge {
 public:
  int e, nxt, cap;
  edge(int e1 = -1, int nxt1 = -1, int cap1 = 0) {
    e = e1, nxt = nxt1, cap = cap1;
  }
};
int S, T;
int dep[2000];
bool vis[2000];
class graph {
 public:
  edge g[1000000];
  int head[2000], tmpcnt;
  int cur[2000];
  void init() {
    memset(head, 255, sizeof(head));
    tmpcnt = 0;
  }
  inline void addedge(int s, int e, int cap) {
    if (cap == 0) return;
    g[tmpcnt] = edge(e, head[s], cap), head[s] = tmpcnt++;
    g[tmpcnt] = edge(s, head[e], 0), head[e] = tmpcnt++;
  }
  bool bfs() {
    memset(vis, 0, sizeof(vis));
    memset(dep, 0, sizeof(dep));
    queue<int> q;
    q.push(S);
    vis[S] = 1;
    while (!q.empty()) {
      int fr = q.front();
      q.pop();
      for (int i = head[fr]; i != -1; i = g[i].nxt) {
        if (g[i].cap > 0 && !vis[g[i].e]) {
          dep[g[i].e] = dep[fr] + 1;
          vis[g[i].e] = 1;
          q.push(g[i].e);
        }
      }
    }
    return vis[T];
  }
  int dfs(int np, int maxflow) {
    int f;
    int flow = 0;
    if (np == T || !maxflow) return maxflow;
    for (int i = cur[np]; i != -1; i = g[i].nxt) {
      cur[np] = i;
      if (g[i].cap > 0 && dep[g[i].e] == dep[np] + 1 &&
          (f = dfs(g[i].e, min(g[i].cap, maxflow))) > 0) {
        g[i].cap -= f;
        g[i ^ 1].cap += f;
        flow += f;
        maxflow -= f;
        if (!maxflow) break;
      }
    }
    return flow;
  }
  int dinic() {
    int out = 0;
    while (bfs()) memcpy(cur, head, sizeof(cur)), out += dfs(S, 0x3f3f3f3f);
    return out;
  }
} G;
inline int id(int x, int y) { return (x - 1) * m + y; }
int dis[30][30];
char s[30][30];
void init(int x, int y) {
  memset(dis, 255, sizeof(dis));
  int st = id(x, y);
  queue<pair<int, int> > q;
  q.push(make_pair(x, y));
  dis[x][y] = 0;
  disp[st][0].push_back(st);
  while (!q.empty()) {
    pair<int, int> fr = q.front();
    q.pop();
    for (int i = 0; i < 4; i++) {
      int nx = fr.first + pos[i][0], ny = fr.second + pos[i][1];
      if (s[nx][ny] == '.' && dis[nx][ny] == -1) {
        dis[nx][ny] = dis[fr.first][fr.second] + 1;
        disp[st][dis[nx][ny]].push_back(id(nx, ny));
        q.push(make_pair(nx, ny));
      }
    }
  }
}
class peo {
 public:
  int x, y, t;
} male[500], female[500];
int main() {
  scanf("%d%d%d%d", &n, &m, &a, &b);
  for (int i = 1; i <= n; i++) scanf("%s", s[i] + 1);
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= m; j++) {
      if (s[i][j] != '#') init(i, j);
    }
  }
  if (b == a + 1) {
    scanf("%d%d%d", &male[a + 1].x, &male[a + 1].y, &male[a + 1].t);
  } else if (a == b + 1) {
    scanf("%d%d%d", &female[b + 1].x, &female[b + 1].y, &female[b + 1].t);
  } else {
    puts("-1");
    return 0;
  }
  int K = max(a, b);
  for (int i = 1; i <= a; i++)
    scanf("%d%d%d", &male[i].x, &male[i].y, &male[i].t);
  for (int i = 1; i <= b; i++)
    scanf("%d%d%d", &female[i].x, &female[i].y, &female[i].t);
  long long L = 0, R = 1ll << 40, ans = -1;
  S = 2 * (K + n * m) + 1;
  T = 2 * (K + n * m) + 2;
  while (L <= R) {
    long long mid = (L + R) >> 1;
    G.init();
    for (int i = 1; i <= K; i++) {
      G.addedge(S, i + 2 * n * m, 1);
      G.addedge(i + K + 2 * n * m, T, 1);
      int pm = id(male[i].x, male[i].y);
      for (int j = 0; j <= mid / male[i].t && j <= n * m; j++) {
        for (auto &x : disp[pm][j]) G.addedge(i + 2 * n * m, x, 1);
      }
      pm = id(female[i].x, female[i].y);
      for (int j = 0; j <= mid / female[i].t && j <= n * m; j++) {
        for (auto &x : disp[pm][j]) G.addedge(x + n * m, i + K + 2 * n * m, 1);
      }
    }
    for (int i = 1; i <= n * m; i++) G.addedge(i, i + n * m, 1);
    if (G.dinic() != K)
      L = mid + 1;
    else
      ans = mid, R = mid - 1;
  }
  printf("%lld\n", ans);
  return 0;
}
