#include <bits/stdc++.h>   using namespace std;   int cap[1000000], flow[1000000];   int to[1000000], _prev[1000000], last[10000], used[10000], level[10000];   struct MaxFlow {     int V, E;     MaxFlow(int n) {       int i;       V = n;       E = 0;       for ((i) = 0; (i) < (int)(V); (i)++) last[i] = -1;     }     void add_edge(int x, int y, int f) {       cap[E] = f;       flow[E] = 0;       to[E] = y;       _prev[E] = last[x];       last[x] = E;       E++;       cap[E] = 0;       flow[E] = 0;       to[E] = x;       _prev[E] = last[y];       last[y] = E;       E++;     }     bool bfs(int s, int t) {       int i;       for ((i) = 0; (i) < (int)(V); (i)++) level[i] = -1;       queue<int> q;       q.push(s);       level[s] = 0;       while (!q.empty()) {         int x = q.front();         q.pop();         for (i = last[x]; i >= 0; i = _prev[i])           if (level[to[i]] == -1 && cap[i] > flow[i]) {             q.push(to[i]);             level[to[i]] = level[x] + 1;           }       }       return (level[t] != -1);     }     int dfs(int v, int t, int f) {       int i;       if (v == t) return f;       for (i = used[v]; i >= 0; used[v] = i = _prev[i])         if (level[to[i]] > level[v] && cap[i] > flow[i]) {           int tmp = dfs(to[i], t, min(f, cap[i] - flow[i]));           if (tmp > 0) {             flow[i] += tmp;             flow[i ^ 1] -= tmp;             return tmp;           }         }       return 0;     }     int maxflow(int s, int t) {       int i;       while (bfs(s, t)) {         for ((i) = 0; (i) < (int)(V); (i)++) used[i] = last[i];         while (dfs(s, t, (1 << 29)) != 0)           ;       }       int ans = 0;       for (i = last[s]; i >= 0; i = _prev[i]) ans += flow[i];       return ans;     }   };   int dx[] = {1, -1, 0, 0}, dy[] = {0, 0, 1, -1};   int X, Y;   string board[30];   int dist[30][30][30][30];   int A, B;   int cx, cy, ct;   int ax[500], ay[500], at[500];   int bx[500], by[500], bt[500];   queue<int> q;   void bfs(int s, int t) {     int i, j;     for ((i) = 0; (i) < (int)(X); (i)++)       for ((j) = 0; (j) < (int)(Y); (j)++) dist[s][t][i][j] = (1 << 29);     if (board[s][t] ==  # ) return;     dist[s][t][s][t] = 0;     q.push(s);     q.push(t);     while (!q.empty()) {       int x = q.front();       q.pop();       int y = q.front();       q.pop();       for ((i) = 0; (i) < (int)(4); (i)++) {         int x2 = x + dx[i], y2 = y + dy[i];         if (x2 >= 0 && x2 < X && y2 >= 0 && y2 < Y && board[x2][y2] !=  #  &&             dist[s][t][x2][y2] == (1 << 29)) {           dist[s][t][x2][y2] = dist[s][t][x][y] + 1;           q.push(x2);           q.push(y2);         }       }     }   }   bool check(long long T) {     int i, j, k;     MaxFlow mf(A + A + 2 * (X * Y) + 2);     int V = A + A + 2 * (X * Y) + 2;     for ((i) = 0; (i) < (int)(A); (i)++) mf.add_edge(V - 2, i, 1);     for ((i) = 0; (i) < (int)(A); (i)++) mf.add_edge(A + i, V - 1, 1);     for ((i) = 0; (i) < (int)(X * Y); (i)++)       mf.add_edge(A + A + i, A + A + X * Y + i, 1);     for ((i) = 0; (i) < (int)(A); (i)++)       for ((j) = 0; (j) < (int)(X); (j)++)         for ((k) = 0; (k) < (int)(Y); (k)++) {           int d = dist[ax[i]][ay[i]][j][k];           if (d != (1 << 29) && (long long)d * at[i] <= T)             mf.add_edge(i, A + A + j * Y + k, 1);         }     for ((i) = 0; (i) < (int)(A); (i)++)       for ((j) = 0; (j) < (int)(X); (j)++)         for ((k) = 0; (k) < (int)(Y); (k)++) {           int d = dist[bx[i]][by[i]][j][k];           if (d != (1 << 29) && (long long)d * bt[i] <= T)             mf.add_edge(A + A + X * Y + j * Y + k, A + i, 1);         }     int f = mf.maxflow(V - 2, V - 1);     return (f == A);   }   int main(void) {     int i, j;     cin >> X >> Y >> A >> B;     for ((i) = 0; (i) < (int)(X); (i)++) cin >> board[i];     for ((i) = 0; (i) < (int)(X); (i)++)       for ((j) = 0; (j) < (int)(Y); (j)++) bfs(i, j);     cin >> cx >> cy >> ct;     for ((i) = 0; (i) < (int)(A); (i)++) cin >> ax[i] >> ay[i] >> at[i];     for ((i) = 0; (i) < (int)(B); (i)++) cin >> bx[i] >> by[i] >> bt[i];     cx--;     cy--;     for ((i) = 0; (i) < (int)(A); (i)++) {       ax[i]--;       ay[i]--;     }     for ((i) = 0; (i) < (int)(B); (i)++) {       bx[i]--;       by[i]--;     }     if (A < B) {       ax[A] = cx;       ay[A] = cy;       at[A] = ct;       A++;     } else {       bx[B] = cx;       by[B] = cy;       bt[B] = ct;       B++;     }     if (A != B) {       cout << -1 << endl;       return 0;     }     long long low = -1, high = (1ll << 40);     while (high - low > 1) {       long long mid = (low + high) / 2;       if (check(mid))         high = mid;       else         low = mid;     }     if (high == (1ll << 40)) high = -1;     cout << high << endl;     return 0;   }