#include <bits/stdc++.h>
using namespace std;
const long long INF = (~0ULL) >> 1;
namespace flow {
struct Edge {
  int u, v;
  long long cap, flow;
  Edge() {}
  Edge(int a, int b, long long c, long long f) {
    u = a, v = b, cap = c, flow = f;
  }
};
vector<int> adj[30010];
vector<struct Edge> E;
int n, s, t, ptr[30010], len[30010], dis[30010], Q[30010];
inline void init(int nodes, int source, int sink) {
  memset(len, 0, sizeof(len));
  E.clear();
  n = nodes, s = source, t = sink;
  for (int i = 0; i < 30010; i++) adj[i].clear();
}
inline void addEdge(int a, int b, long long c) {
  adj[a].push_back(E.size());
  E.push_back(Edge(a, b, c, 0));
  len[a]++;
  adj[b].push_back(E.size());
  E.push_back(Edge(b, a, 0, 0));
  len[b]++;
}
inline bool bfs() {
  int i, j, k, id, f = 0, l = 0;
  memset(dis, -1, sizeof(dis[0]) * n);
  dis[s] = 0, Q[l++] = s;
  while (f < l && dis[t] == -1) {
    i = Q[f++];
    for (k = 0; k < len[i]; k++) {
      id = adj[i][k];
      if (dis[E[id].v] == -1 && E[id].flow < E[id].cap) {
        Q[l++] = E[id].v;
        dis[E[id].v] = dis[i] + 1;
      }
    }
  }
  return (dis[t] != -1);
}
long long dfs(int i, long long f) {
  if (i == t || !f) return f;
  while (ptr[i] < len[i]) {
    int id = adj[i][ptr[i]];
    if (dis[E[id].v] == dis[i] + 1) {
      long long x = dfs(E[id].v, min(f, E[id].cap - E[id].flow));
      if (x) {
        E[id].flow += x, E[id ^ 1].flow -= x;
        return x;
      }
    }
    ptr[i]++;
  }
  return 0;
}
long long dinic() {
  long long res = 0;
  while (bfs()) {
    memset(ptr, 0, n * sizeof(ptr[0]));
    while (long long f = dfs(s, INF)) {
      res += f;
    }
  }
  return res;
}
}  // namespace flow
const int N = 23, NN = N * N;
string g[N];
int dis[NN][NN];
int dx[4] = {1, -1, 0, 0};
int dy[4] = {0, 0, 1, -1};
bool isvalid(int x, int y, int n, int m) {
  return 0 <= x && x < n && 0 <= y && y < m && g[x][y] == '.';
}
vector<vector<pair<int, long long>>> dm, df;
int n, m, a, b;
void process(vector<vector<pair<int, long long>>> &d) {
  int x, y, v;
  cin >> x >> y >> v;
  x--;
  y--;
  int id = x * m + y;
  d.emplace_back();
  for (int i = 0; i < n * m; i++) {
    if (dis[id][i] >= NN) continue;
    d.back().push_back({i, 1LL * v * dis[id][i]});
  }
}
int main() {
  cin >> n >> m >> a >> b;
  for (int i = 0; i < NN; i++) {
    for (int j = 0; j < NN; j++) dis[i][j] = NN;
    dis[i][i] = 0;
  }
  for (int i = 0; i < n; i++) cin >> g[i];
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      if (g[i][j] == '#') continue;
      for (int dd = 0; dd < 4; dd++) {
        int nx = i + dx[dd];
        int ny = j + dy[dd];
        if (isvalid(nx, ny, n, m)) dis[i * m + j][nx * m + ny] = 1;
      }
    }
  }
  for (int k = 0; k < n * m; k++)
    for (int i = 0; i < n * m; i++)
      for (int j = 0; j < n * m; j++)
        dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
  if (a == b + 1)
    process(df);
  else if (b == a + 1)
    process(dm);
  else {
    cout << -1 << endl;
    return 0;
  }
  for (int i = 0; i < a; i++) process(dm);
  for (int i = 0; i < b; i++) process(df);
  assert(df.size() == dm.size());
  a = df.size();
  const long long INF = 1e12;
  long long lo = 0, hi = INF;
  while (lo < hi) {
    long long mid = (lo + hi) / 2;
    int sz = 2 * n * m + a + a + 2;
    int sink = sz - 1, source = sz - 2;
    flow::init(sz, source, sink);
    for (int i = 0; i < a; i++) {
      flow::addEdge(source, 2 * n * m + i, 1);
      for (auto pr : dm[i]) {
        if (pr.second > mid) continue;
        flow::addEdge(2 * n * m + i, pr.first, 1);
      }
    }
    for (int i = 0; i < a; i++) {
      flow::addEdge(2 * n * m + a + i, sink, 1);
      for (auto pr : df[i]) {
        if (pr.second > mid) continue;
        flow::addEdge(n * m + pr.first, 2 * n * m + a + i, 1);
      }
    }
    for (int i = 0; i < n * m; i++) flow::addEdge(i, n * m + i, 1);
    int ff = flow::dinic();
    if (ff == a)
      hi = mid;
    else
      lo = mid + 1;
  }
  if (lo == INF) lo = -1;
  cout << lo << endl;
}
