#include <bits/stdc++.h>
using namespace std;
const int INF = 1000000000;
struct Edge {
  int a, b, cap, flow;
};
struct MaxFlow {
  int n, s, t;
  vector<int> d, ptr, q;
  vector<Edge> e;
  vector<vector<int> > g;
  MaxFlow(int n) : n(n), d(n), ptr(n), g(n), q(n) {
    e.clear();
    for (int i = 0, _a = (n); i < _a; i++) {
      g[i].clear();
      ptr[i] = 0;
    }
  }
  void addEdge(int a, int b, int cap) {
    Edge e1 = {a, b, cap, 0};
    Edge e2 = {b, a, 0, 0};
    g[a].push_back((int)e.size());
    e.push_back(e1);
    g[b].push_back((int)e.size());
    e.push_back(e2);
  }
  int getMaxFlow(int _s, int _t) {
    s = _s;
    t = _t;
    int flow = 0;
    for (;;) {
      if (!bfs()) break;
      for (int i = 0, _a = (n); i < _a; i++) ptr[i] = 0;
      while (int pushed = dfs(s, INF)) flow += pushed;
    }
    return flow;
  }

 private:
  bool bfs() {
    int qh = 0, qt = 0;
    q[qt++] = s;
    for (int i = 0, _a = (n); i < _a; i++) d[i] = -1;
    d[s] = 0;
    while (qh < qt && d[t] == -1) {
      int v = q[qh++];
      for (int i = 0, _a = (g[v].size()); i < _a; i++) {
        int id = g[v][i], to = e[id].b;
        if (d[to] == -1 && e[id].flow < e[id].cap) {
          q[qt++] = to;
          d[to] = d[v] + 1;
        }
      }
    }
    return d[t] != -1;
  }
  int dfs(int v, int flow) {
    if (!flow) return 0;
    if (v == t) return flow;
    for (; ptr[v] < (int)g[v].size(); ++ptr[v]) {
      int id = g[v][ptr[v]], to = e[id].b;
      if (d[to] != d[v] + 1) continue;
      int pushed = dfs(to, min(flow, e[id].cap - e[id].flow));
      if (pushed) {
        e[id].flow += pushed;
        e[id ^ 1].flow -= pushed;
        return pushed;
      }
    }
    return 0;
  }
};
string board[30];
int d[600][600];
int dx[4] = {-1, 1, 0, 0};
int dy[4] = {0, 0, -1, 1};
long long inf = (1e6);
int src, sink, sz;
MaxFlow G(1);
int n, m, males, females;
int allSz;
struct deer {
  long long x, y, spd;
  deer(int xx, int yy, int spdd) : x(xx), y(yy), spd(spdd) {}
};
vector<deer> maleList, femaleList;
void addMale(int x, int y, long long spd, long long bound) {
  x--;
  y--;
  G.addEdge(src, sz, 1);
  int now = x * m + y;
  for (int i = 0; i < n * m; ++i) {
    if (d[now][i] != inf) {
      if (d[now][i] * spd <= bound) {
        G.addEdge(sz, i, 1);
      }
    }
  }
  sz++;
}
void addFemale(int x, int y, long long spd, long long bound) {
  x--;
  y--;
  G.addEdge(sz, sink, 1);
  int now = x * m + y;
  for (int i = 0; i < n * m; ++i) {
    if (d[now][i] != inf) {
      if (d[now][i] * spd <= bound) G.addEdge(allSz - i - 1, sz, 1);
    }
  }
  sz++;
}
bool visited[30][30];
int main() {
  cin >> n >> m >> males >> females;
  if (abs(males - females) != 1) {
    cout << -1;
    return 0;
  }
  for (int i = 0; i < 600; ++i) {
    for (int j = 0; j < 600; ++j) d[i][j] = inf;
  }
  for (int i = 0; i < n; ++i) cin >> board[i];
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < m; ++j) {
      if (board[i][j] == '#') {
        continue;
      }
      d[i * m + j][i * m + j] = 0;
      for (int dir = 0; dir < 4; ++dir) {
        int x = i + dx[dir];
        int y = j + dy[dir];
        if (x < 0 || x >= n || y < 0 || y >= m) continue;
        if (board[x][y] == '.') d[i * m + j][x * m + y] = 1;
      }
    }
  }
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < m; ++j) {
      memset(visited, 0, sizeof(visited));
      if (board[i][j] == '.') {
        queue<pair<int, pair<int, int> > > q;
        q.push({0, {i, j}});
        visited[i][j] = 1;
        while (!q.empty()) {
          auto cur = q.front();
          d[i * m + j][cur.second.first * m + cur.second.second] = cur.first;
          q.pop();
          for (int dir = 0; dir < 4; ++dir) {
            int x = cur.second.first + dx[dir];
            int y = cur.second.second + dy[dir];
            if (x < 0 || x >= n || y < 0 || y >= m) continue;
            if (board[x][y] == '.' && !visited[x][y]) {
              visited[x][y] = 1;
              q.push({cur.first + 1, {x, y}});
            }
          }
        }
      }
    }
  }
  src = n * m;
  sink = n * m + 1;
  long long x, y, spd;
  cin >> x >> y >> spd;
  if (males < females) {
    maleList.push_back(deer(x, y, spd));
  } else {
    femaleList.push_back(deer(x, y, spd));
  }
  for (int i = 0; i < males; ++i) {
    cin >> x >> y >> spd;
    maleList.push_back(deer(x, y, spd));
  }
  for (int i = 0; i < females; ++i) {
    cin >> x >> y >> spd;
    femaleList.push_back(deer(x, y, spd));
  }
  int req = males + females + 1;
  req /= 2;
  long long mAns = -1;
  long long bs = 0, be = (1LL << 40);
  while (bs <= be) {
    G = MaxFlow(2 + males + females + 1 + n * m * 2 + 5);
    allSz = 2 + males + females + 1 + n * m * 2 + 5;
    for (int i = 0; i < n * m; ++i) {
      G.addEdge(i, allSz - i - 1, 1);
    }
    sz = n * m + 2;
    long long mid = (bs + be) / 2;
    for (int i = 0; i < maleList.size(); ++i) {
      addMale(maleList[i].x, maleList[i].y, maleList[i].spd, mid);
    }
    for (int i = 0; i < femaleList.size(); ++i) {
      addFemale(femaleList[i].x, femaleList[i].y, femaleList[i].spd, mid);
    }
    int ans = G.getMaxFlow(src, sink);
    if (ans == req) {
      mAns = mid;
      be = mid - 1;
    } else {
      bs = mid + 1;
    }
  }
  cout << mAns << endl;
}
