#include <bits/stdc++.h>   using namespace std;   const int N = 23, MXN = N * N * 4;   struct Edge {     int to, flow;   };   struct Dinic {     int s, t, P[MXN], D[MXN], qu[MXN];     vector<int> Adj[MXN];     vector<Edge> E;     inline void Add(int v, int u, int w) {       Adj[v].push_back(E.size());       E.push_back({u, w});       Adj[u].push_back(E.size());       E.push_back({v, 0});     }     inline bool BFS() {       int l = 0, r = 0;       memset(D, -1, sizeof(D));       D[s] = 0;       qu[r++] = s;       while (r - l) {         int v = qu[l++];         for (int &id : Adj[v])           if (E[id].flow && D[E[id].to] == -1)             D[E[id].to] = D[v] + 1, qu[r++] = E[id].to;       }       return (D[t] != -1);     }     int DFS(int v, int flow) {       if (v == t) return flow;       int Flow = 0;       for (int i = P[v]; i < Adj[v].size(); i++) {         int id = Adj[v][i];         if (E[id].flow && D[E[id].to] == D[v] + 1) {           int sub = DFS(E[id].to, min(flow, E[id].flow));           if (!sub) {             swap(Adj[v][i], Adj[v][P[v]]);             P[v]++;             continue;           }           E[id].flow -= sub;           E[id ^ 1].flow += sub;           flow -= sub;           Flow += sub;           if (!flow) return Flow;         } else           swap(Adj[v][i], Adj[v][P[v]]), P[v]++;       }       return Flow;     }     inline int MaxFlow(int _s, int _t) {       int Flow = 0;       s = _s;       t = _t;       while (BFS()) {         memset(P, 0, sizeof(P));         Flow += DFS(s, INT_MAX);       }       return Flow;     }   };   int n, m, D[N][N], gg[] = {-1, 1, 0, 0};   int fl, ml, X[MXN], Y[MXN], T[MXN];   pair<int, int> qu[MXN];   char S[N][N];   vector<vector<long long> > E;   inline bool Solve(int md) {     Dinic G;     int s = ml + fl + n * m * 2, t = s + 1;     for (int i = 0; i < ml; i++) G.Add(s, i, 1);     for (int i = 0; i < fl; i++) G.Add(i + ml, t, 1);     for (int i = 0; i < n; i++)       for (int j = 0; j < m; j++)         G.Add(ml + fl + i + j * n, ml + fl + i + j * n + n * m, 1);     for (int i = 0; i <= md; i++) {       int id = E[i][1], cell = n * E[i][3] + E[i][2] + ml + fl;       if (id < ml)         G.Add(id, cell, 1);       else         G.Add(cell + n * m, id, 1);     }     return (G.MaxFlow(s, t) == ml);   }   int main() {     scanf( %d%d%d%d , &n, &m, &ml, &fl);     if (abs(ml - fl) != 1) return !printf( -1 );     for (int i = 0; i < n; i++) scanf( %s , &S[i]);     if (ml < fl)       scanf( %d%d%d , &X[ml], &Y[ml], &T[ml]);     else       scanf( %d%d%d , &X[ml + fl], &Y[ml + fl], &T[ml + fl]);     for (int i = 0; i < ml; i++) scanf( %d%d%d , &X[i], &Y[i], &T[i]);     if (ml < fl) ml++;     for (int i = ml; i < ml + fl; i++) scanf( %d%d%d , &X[i], &Y[i], &T[i]);     if (fl < ml) fl++;     for (int i = 0; i < ml + fl; i++) {       int l = 0, r = 0;       memset(D, -1, sizeof(D));       X[i]--;       Y[i]--;       D[X[i]][Y[i]] = 0;       qu[r++] = {X[i], Y[i]};       while (r - l) {         int a = qu[l].first, b = qu[l++].second;         E.push_back({1LL * D[a][b] * T[i], i, a, b});         for (int h = 0; h < 4; h++) {           int ta = a + gg[h], tb = b + gg[(h + 2) % 4];           if (ta < 0 || tb < 0 || ta >= n || tb >= m) continue;           if (S[ta][tb] ==  #  || D[ta][tb] != -1) continue;           D[ta][tb] = D[a][b] + 1;           qu[r++] = {ta, tb};         }       }     }     sort(E.begin(), E.end());     int le = -1, ri = E.size(), md;     while (ri - le > 1) {       md = (le + ri) >> 1;       if (Solve(md))         ri = md;       else         le = md;     }     if (ri < E.size()) return !printf( %lld , E[ri][0]);     return !printf( -1 );   }