#include <bits/stdc++.h>
using namespace std;
template <class C>
void mini(C& a4, C b4) {
  a4 = min(a4, b4);
}
template <class C>
void maxi(C& a4, C b4) {
  a4 = max(a4, b4);
}
template <class T1, class T2>
ostream& operator<<(ostream& out, pair<T1, T2> pair) {
  return out << "(" << pair.first << ", " << pair.second << ")";
}
template <class A, class B, class C>
struct Triple {
  A first;
  B second;
  C third;
};
template <class T>
void ResizeVec(T&, vector<long long>) {}
template <class T>
void ResizeVec(vector<T>& vec, vector<long long> sz) {
  vec.resize(sz[0]);
  sz.erase(sz.begin());
  if (sz.empty()) {
    return;
  }
  for (T& v : vec) {
    ResizeVec(v, sz);
  }
}
struct Edge {
  long long v, c, inv;
  Edge(long long v_, long long c_, long long inv_) {
    v = v_;
    c = c_;
    inv = inv_;
  }
};
struct Dinic {
 public:
  Dinic() { n = -1; }
  void AddEdge(long long a, long long b, long long cap, long long bi_dir = 0) {
    if (n < max(a, b)) {
      n = max(n, max(a, b));
      ResizeVectors();
    }
    e_orig[a].push_back(Edge(b, cap, ((long long)(e_orig[b]).size())));
    e_orig[b].push_back(
        Edge(a, bi_dir * cap, ((long long)(e_orig[a]).size()) - 1));
  }
  long long MaxFlow(long long s, long long t) {
    e = e_orig;
    long long result = 0;
    while (Bfs(s, t)) {
      for (long long i = 0; i <= n; i++) {
        beg[i] = 0;
      }
      result += Dfs(s, t, kInf);
    }
    return result;
  }

 private:
  long long n;
  vector<vector<Edge> > e_orig;
  vector<vector<Edge> > e;
  vector<long long> beg;
  vector<long long> dis;
  bool Bfs(long long s, long long t) {
    for (long long i = 0; i <= n; i++) {
      dis[i] = n + 1;
    }
    dis[s] = 0;
    vector<long long> que;
    que.push_back(s);
    for (long long i = 0; i < ((long long)(que).size()); i++) {
      long long v = que[i];
      for (long long j = 0; j < ((long long)(e[v]).size()); j++) {
        long long nei = e[v][j].v;
        if (e[v][j].c && dis[nei] > dis[v] + 1) {
          dis[nei] = dis[v] + 1;
          que.push_back(nei);
          if (nei == t) {
            return true;
          }
        }
      }
    }
    return false;
  }
  long long Dfs(long long v, long long t, long long min_cap) {
    long long result = 0;
    if (v == t || min_cap == 0) {
      return min_cap;
    }
    for (long long& i = beg[v]; i < ((long long)(e[v]).size()); i++) {
      long long nei = e[v][i].v;
      long long c = e[v][i].c;
      if (dis[nei] == dis[v] + 1 && c > 0) {
        long long flow_here = Dfs(nei, t, min(min_cap, c));
        result += flow_here;
        min_cap -= flow_here;
        e[v][i].c -= flow_here;
        e[nei][e[v][i].inv].c += flow_here;
      }
      if (min_cap == 0) {
        break;
      }
    }
    return result;
  }
  void ResizeVectors() {
    e_orig.resize(n + 2);
    beg.resize(n + 2);
    dis.resize(n + 2);
  }
  static const long long kInf = 1e18;
};
const long long kInf = 1e15;
struct Guy {
  long long r, c, speed;
};
Guy ReadGuy() {
  long long r, c, sp;
  cin >> r >> c >> sp;
  ;
  return {r, c, sp};
}
vector<Guy> fem, mal;
void ReadFem() { fem.push_back(ReadGuy()); }
void ReadMal() { mal.push_back(ReadGuy()); }
const long long N = 25;
long long can[N][N];
long long dis[N][N][N][N];
long long di[] = {-1, 1, 0, 0};
long long dj[] = {0, 0, 1, -1};
int main() {
  ios_base::sync_with_stdio(0);
  cout << fixed << setprecision(10);
  double beg_clock = 1.0 * clock() / CLOCKS_PER_SEC;
  long long n, m, mal_num, fem_num;
  cin >> n >> m >> mal_num >> fem_num;
  ;
  if (abs(mal_num - fem_num) != 1) {
    cout << "-1\n";
    return 0;
  }
  for (long long r = (1); r <= (n); ++r) {
    for (long long c = (1); c <= (m); ++c) {
      char ch;
      cin >> ch;
      ;
      if (ch == '.') {
        can[r][c] = 1;
      }
    }
  }
  if (mal_num < fem_num) {
    ReadMal();
  } else {
    ReadFem();
  }
  for (long long i = (1); i <= (mal_num); ++i) {
    ReadMal();
  }
  for (long long i = (1); i <= (fem_num); ++i) {
    ReadFem();
  }
  for (long long r = (1); r <= (n); ++r) {
    for (long long c = (1); c <= (m); ++c) {
      for (long long i = (1); i <= (n); ++i) {
        for (long long j = (1); j <= (m); ++j) {
          dis[r][c][i][j] = kInf;
        }
      }
      if (!can[r][c]) {
        continue;
      }
      vector<pair<long long, long long> > que;
      que.push_back(make_pair(r, c));
      dis[r][c][r][c] = 0;
      for (long long ii = 0; ii < ((long long)(que).size()); ii++) {
        auto p = que[ii];
        long long cur_i = p.first;
        long long cur_j = p.second;
        for (long long dir = 0; dir < (4); ++dir) {
          long long new_i = cur_i + di[dir];
          long long new_j = cur_j + dj[dir];
          if (!can[new_i][new_j]) {
            continue;
          }
          if (dis[r][c][new_i][new_j] == kInf) {
            dis[r][c][new_i][new_j] = dis[r][c][cur_i][cur_j] + 1;
            que.push_back(make_pair(new_i, new_j));
          }
        }
      }
    }
  }
  long long kl = 0, kp = 1e12, faj = -1;
  while (kl <= kp) {
    long long aktc = (kl + kp) / 2;
    Dinic gr;
    long long s = 0;
    long long t = 4 * n * m + 1;
    for (long long ii = 0; ii < ((long long)(fem).size()); ii++) {
      auto g = fem[ii];
      gr.AddEdge(s, 1 + ii, 1);
      for (long long r = (1); r <= (n); ++r) {
        for (long long c = (1); c <= (m); ++c) {
          if (dis[r][c][g.r][g.c] < kInf &&
              dis[r][c][g.r][g.c] * g.speed <= aktc) {
            gr.AddEdge(1 + ii, n * m + (r - 1) * m + c, 1);
          }
        }
      }
    }
    for (long long ii = 0; ii < ((long long)(mal).size()); ii++) {
      auto g = mal[ii];
      gr.AddEdge(3 * n * m + 1 + ii, t, 1);
      for (long long r = (1); r <= (n); ++r) {
        for (long long c = (1); c <= (m); ++c) {
          if (dis[r][c][g.r][g.c] < kInf &&
              dis[r][c][g.r][g.c] * g.speed <= aktc) {
            gr.AddEdge(2 * n * m + (r - 1) * m + c, 3 * n * m + 1 + ii, 1);
          }
        }
      }
    }
    for (long long r = (1); r <= (n); ++r) {
      for (long long c = (1); c <= (m); ++c) {
        gr.AddEdge(n * m + (r - 1) * m + c, 2 * n * m + (r - 1) * m + c, 1);
      }
    }
    if (gr.MaxFlow(s, t) == ((long long)(mal).size())) {
      faj = aktc;
      kp = aktc - 1;
    } else {
      kl = aktc + 1;
    }
  }
  cout << faj << "\n";
  return 0;
}
