#include <bits/stdc++.h>
template <class T>
inline bool rd(T &ret) {
  char c;
  int sgn;
  if (c = getchar(), c == EOF) return 0;
  while (c != '-' && (c < '0' || c > '9')) c = getchar();
  sgn = (c == '-') ? -1 : 1;
  ret = (c == '-') ? 0 : (c - '0');
  while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
  ret *= sgn;
  return 1;
}
template <class T>
inline void pt(T x) {
  if (x < 0) {
    putchar('-');
    x = -x;
  }
  if (x > 9) pt(x / 10);
  putchar(x % 10 + '0');
}
using namespace std;
const long long inf = 1000000000000L;
const int N = 605;
const int M = N * N * 10;
struct Edge {
  long long to, cap, cost, nex;
  Edge() {}
  Edge(long long to, long long cap, long long cost, long long next)
      : to(to), cap(cap), cost(cost), nex(next) {}
} edge[M << 1];
long long head[N], edgenum;
long long D[N], A[N], P[N];
bool inq[N];
void add(long long from, long long to, long long cap, long long cost) {
  edge[edgenum] = Edge(to, cap, cost, head[from]);
  head[from] = edgenum++;
  edge[edgenum] = Edge(from, 0, -cost, head[to]);
  head[to] = edgenum++;
}
bool spfa(long long s, long long t, long long &flow, long long &cost) {
  for (long long i = 0; i <= t; i++) D[i] = inf;
  memset(inq, 0, sizeof inq);
  queue<long long> q;
  q.push(s);
  D[s] = 0;
  A[s] = inf;
  while (!q.empty()) {
    long long u = q.front();
    q.pop();
    inq[u] = 0;
    for (long long i = head[u]; ~i; i = edge[i].nex) {
      Edge &e = edge[i];
      if (e.cap && D[e.to] > D[u] + e.cost) {
        D[e.to] = D[u] + e.cost;
        P[e.to] = i;
        A[e.to] = min(A[u], e.cap);
        if (!inq[e.to]) {
          inq[e.to] = 1;
          q.push(e.to);
        }
      }
    }
  }
  if (D[t] == inf) return false;
  cost += D[t] * A[t];
  flow += A[t];
  long long u = t;
  while (u != s) {
    edge[P[u]].cap -= A[t];
    edge[P[u] ^ 1].cap += A[t];
    u = edge[P[u] ^ 1].to;
  }
  return true;
}
long long Mincost(long long s, long long t) {
  long long flow = 0, cost = 0;
  while (spfa(s, t, flow, cost))
    ;
  return flow;
}
void init() {
  memset(head, -1, sizeof head);
  edgenum = 0;
}
struct node {
  int x, y;
  long long t;
  node(int a = 0, int b = 0, long long c = 0) : x(a), y(b), t(c) {}
} AA[N], B[N], C;
int n, m, a, b;
char mp[13][13];
long long Dis[13][13][13][13];
int has1(int x) { return x - 1; }
int has2(int x, int y) { return a + (x - 1) * m + y - 1; }
int has3(int x, int y) { return a + n * m + (x - 1) * m + y - 1; }
int has4(int x) { return a + 2 * n * m + x - 1; }
bool ok(long long now) {
  int from = has4(b) + 1, to = from + 1;
  init();
  for (int i = 1; i <= a; i++) {
    add(from, has1(i), 1, 0);
    for (int x = 1; x <= n; x++)
      for (int y = 1; y <= m; y++)
        if (Dis[x][y][AA[i].x][AA[i].y] < inf &&
            Dis[x][y][AA[i].x][AA[i].y] * AA[i].t <= now)
          add(has1(i), has2(x, y), 1, 0);
  }
  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= m; j++)
      if (mp[i][j] == '.') add(has2(i, j), has3(i, j), 1, 0);
  for (int i = 1; i <= b; i++) {
    add(has4(i), to, 1, 0);
    for (int x = 1; x <= n; x++)
      for (int y = 1; y <= m; y++)
        if (Dis[x][y][B[i].x][B[i].y] < inf &&
            Dis[x][y][B[i].x][B[i].y] * B[i].t <= now)
          add(has3(x, y), has4(i), 1, 0);
  }
  return Mincost(from, to) == b;
}
long long solve() {
  if (a != b) return -1;
  long long ans = -1, l = 0, r = inf;
  while (l <= r) {
    long long mid = (l + r) >> 1;
    if (ok(mid)) {
      r = mid - 1;
      ans = mid;
    } else
      l = mid + 1;
  }
  return ans;
}
void pre() {
  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= m; j++)
      for (int x = 1; x <= n; x++)
        for (int y = 1; y <= m; y++) Dis[i][j][x][y] = inf;
  int step[4][2] = {0, 1, 0, -1, 1, 0, -1, 0};
  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= m; j++) {
      if (mp[i][j] == '*') continue;
      Dis[i][j][i][j] = 0;
      for (int k = 0; k < 4; k++) {
        int x = i + step[k][0], y = j + step[k][1];
        if (1 <= x && x <= n && 1 <= y && y <= m && mp[x][y] == '.')
          Dis[i][j][x][y] = 1;
      }
    }
  for (int x1 = 1; x1 <= n; x1++)
    for (int y1 = 1; y1 <= m; y1++)
      if (mp[x1][y1] == '.')
        for (int x2 = 1; x2 <= n; x2++)
          for (int y2 = 1; y2 <= m; y2++)
            if (mp[x2][y2] == '.' && Dis[x2][y2][x1][y1] < inf)
              for (int x3 = 1; x3 <= n; x3++)
                for (int y3 = 1; y3 <= m; y3++)
                  if (mp[x3][y3] == '.')
                    Dis[x2][y2][x3][y3] =
                        min(Dis[x2][y2][x3][y3],
                            Dis[x2][y2][x1][y1] + Dis[x1][y1][x3][y3]);
  if (a > b)
    B[++b] = C;
  else
    AA[++a] = C;
}
void input() {
  rd(n);
  rd(m);
  rd(a);
  rd(b);
  for (int i = 1; i <= n; i++) scanf("%s", mp[i] + 1);
  rd(C.x);
  rd(C.y);
  rd(C.t);
  for (int i = 1; i <= a; i++) {
    rd(AA[i].x);
    rd(AA[i].y);
    rd(AA[i].t);
  }
  for (int i = 1; i <= b; i++) {
    rd(B[i].x);
    rd(B[i].y);
    rd(B[i].t);
  }
}
int main() {
  input();
  pre();
  cout << solve() << endl;
  return 0;
}
