#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 = 1e10;   const int N = 10019;   const int M = 10000000;   template <class T>   struct Max_Flow {     int n;     int Q[N], sign;     int head[N], level[N], cur[N], pre[N];     int nxt[M], pnt[M], E;     T cap[M];     void Init(int n) {       this->n = n + 1;       E = 0;       std::fill(head, head + this->n, -1);     }     void add(int from, int to, T c, T rw) {       pnt[E] = to;       cap[E] = c;       nxt[E] = head[from];       head[from] = E++;       pnt[E] = from;       cap[E] = rw;       nxt[E] = head[to];       head[to] = E++;     }     bool Bfs(int s, int t) {       sign = t;       std::fill(level, level + n, -1);       int *front = Q, *tail = Q;       *tail++ = t;       level[t] = 0;       while (front < tail && level[s] == -1) {         int u = *front++;         for (int e = head[u]; e != -1; e = nxt[e]) {           if (cap[e ^ 1] > 0 && level[pnt[e]] < 0) {             level[pnt[e]] = level[u] + 1;             *tail++ = pnt[e];           }         }       }       return level[s] != -1;     }     void Push(int t, T &flow) {       T mi = inf;       int p = pre[t];       for (int p = pre[t]; p != -1; p = pre[pnt[p ^ 1]]) {         mi = std::min(mi, cap[p]);       }       for (int p = pre[t]; p != -1; p = pre[pnt[p ^ 1]]) {         cap[p] -= mi;         if (!cap[p]) {           sign = pnt[p ^ 1];         }         cap[p ^ 1] += mi;       }       flow += mi;     }     void Dfs(int u, int t, T &flow) {       if (u == t) {         Push(t, flow);         return;       }       for (int &e = cur[u]; e != -1; e = nxt[e]) {         if (cap[e] > 0 && level[u] - 1 == level[pnt[e]]) {           pre[pnt[e]] = e;           Dfs(pnt[e], t, flow);           if (level[sign] > level[u]) {             return;           }           sign = t;         }       }     }     T Dinic(int s, int t) {       pre[s] = -1;       T flow = 0;       while (Bfs(s, t)) {         std::copy(head, head + n, cur);         Dfs(s, t, flow);       }       return flow;     }   };   Max_Flow<long long> F;   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[24][24];   long long Dis[24][24][24][24];   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;     F.Init(to + 10);     for (int i = 1; i <= a; i++) {       F.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)             F.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] ==  . ) F.add(has2(i, j), has3(i, j), 1, 0);     for (int i = 1; i <= b; i++) {       F.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)             F.add(has3(x, y), has4(i), 1, 0);     }     return F.Dinic(from, to) == b;   }   long long solve() {     if (a != b) return -1;     long long ans = -1, l = 0, r = 1e18;     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;   }