#include <bits/stdc++.h>
using namespace std;
const int DELTA[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
struct Person {
  int sx;
  int sy;
  int speed;
  vector<pair<int, long long> > edges;
  void read() {
    cin >> sx >> sy >> speed;
    --sx;
    --sy;
  }
  void buildEdge(char field[][30], int m, int n) {
    edges.push_back(make_pair(sx * n + sy, 0));
    vector<vector<bool> > visited(m, vector<bool>(n));
    visited[sx][sy] = true;
    for (int ptr = 0; ptr < (int)edges.size(); ++ptr) {
      int x = edges[ptr].first / n;
      int y = edges[ptr].first % n;
      long long dist = edges[ptr].second;
      for (int dir = 0; dir < 4; ++dir) {
        int nx = x + DELTA[dir][0];
        int ny = y + DELTA[dir][1];
        if (nx >= 0 && nx < m && ny >= 0 && ny < n && field[nx][ny] != '#' &&
            !visited[nx][ny]) {
          visited[nx][ny] = true;
          edges.push_back(make_pair(nx * n + ny, dist + speed));
        }
      }
    }
  }
};
const int N = (int)2e6;
int firstEdge[N];
int nextEdge[N];
int pointTo[N];
int layer[N];
int cap[N];
int work[N];
char field[30][30];
Person males[500];
Person females[500];
int numPeople;
int m;
int n;
int ptr;
void addFlowEdge(int u, int v, int c1, int c2 = 0) {
  pointTo[ptr] = v;
  cap[ptr] = c1;
  nextEdge[ptr] = firstEdge[u];
  firstEdge[u] = ptr++;
  pointTo[ptr] = u;
  cap[ptr] = c2;
  nextEdge[ptr] = firstEdge[v];
  firstEdge[v] = ptr++;
}
bool bfs(int source, int sink) {
  memset(layer, -1, sizeof layer);
  layer[0] = source;
  queue<int> q;
  q.push(source);
  while (!q.empty()) {
    int u = q.front();
    q.pop();
    for (int e = firstEdge[u]; e != -1; e = nextEdge[e])
      if (cap[e] > 0) {
        int v = pointTo[e];
        if (layer[v] == -1) {
          layer[v] = layer[u] + 1;
          q.push(v);
        }
      }
  }
  return layer[sink] != -1;
}
int dfs(int u, int sink, int flow) {
  if (u == sink) return flow;
  for (int &e = work[u]; e != -1; e = nextEdge[e])
    if (cap[e] > 0) {
      int v = pointTo[e];
      if (layer[u] + 1 != layer[v]) continue;
      int result = dfs(v, sink, min(flow, cap[e]));
      if (result != 0) {
        cap[e] -= result;
        cap[e ^ 1] += result;
        return result;
      }
    }
  return 0;
}
int getMaxFlow(int source, int sink) {
  int result = 0;
  while (bfs(source, sink)) {
    memcpy(work, firstEdge, sizeof work);
    for (int delta = 0; (delta = dfs(source, sink, (int)1e9)) != 0;
         result += delta)
      ;
  }
  return result;
}
bool possible(long long maxTime) {
  memset(firstEdge, -1, sizeof firstEdge);
  ptr = 0;
  int source = 0;
  int sink = 1;
  for (int i = 0; i < m * n; ++i) {
    addFlowEdge(i + 2, i + 2 + m * n, 1);
  }
  for (int i = 0; i < numPeople; ++i) {
    addFlowEdge(source, 2 * m * n + 2 + i, 1);
    addFlowEdge(2 * m * n + 2 + numPeople + i, sink, 1);
    for (auto e : males[i].edges) {
      if (e.second > maxTime) break;
      addFlowEdge(2 * m * n + 2 + i, e.first + 2, 1);
    }
    for (auto e : females[i].edges) {
      if (e.second > maxTime) break;
      addFlowEdge(e.first + 2 + m * n, 2 * m * n + 2 + numPeople + i, 1);
    }
  }
  if (getMaxFlow(source, sink) == numPeople) return true;
  return false;
}
int main() {
  ios::sync_with_stdio(false);
  cin >> m >> n;
  int numMales;
  cin >> numMales;
  int numFemales;
  cin >> numFemales;
  for (int i = 0; i < m; ++i) cin >> field[i];
  if (abs(numMales - numFemales) != 1) {
    puts("-1");
    return 0;
  }
  numPeople = max(numMales, numFemales);
  if (numMales < numFemales)
    males[numPeople - 1].read();
  else
    females[numPeople - 1].read();
  for (int i = 0; i < numMales; ++i) males[i].read();
  for (int i = 0; i < numFemales; ++i) females[i].read();
  for (int i = 0; i < numPeople; ++i) {
    males[i].buildEdge(field, m, n);
    females[i].buildEdge(field, m, n);
  }
  long long low = 0;
  long long high = (long long)1e15;
  while (low < high) {
    long long mid = (low + high) / 2;
    if (possible(mid))
      high = mid;
    else
      low = mid + 1;
  }
  cout << (low == (long long)1e15 ? -1 : low) << endl;
  return 0;
}
