#include <bits/stdc++.h>
const static long long INF = std::numeric_limits<long long>::max() / 2 - 1;
struct DinicFlow {
  struct edge {
    long long a, b;
    long long flow, cap;
    edge* rev;
    edge(const long long& _a, const long long& _b, const long long& _flow,
         const long long& _cap, edge* _rev = nullptr)
        : a(_a), b(_b), flow(_flow), cap(_cap), rev(_rev) {}
  };
  typedef std::vector<std::vector<edge*>> adj_list;
  std::vector<char> blocked;
  std::vector<long long> distances;
  adj_list graph;
  long long n;
  long long source;
  long long sink;
  DinicFlow(const long long& _n) : n(_n) {
    source = n++;
    sink = n++;
    blocked.assign(n, false);
    distances.assign(n, INF);
    graph.assign(n, std::vector<edge*>());
  }
  ~DinicFlow(void) {
    for (auto& row : graph) {
      for (auto& e : row) {
        delete e;
      }
    }
  }
  edge* add_edge(const long long& a, const long long& b, const long long& cap,
                 const long long& flow = 0) {
    edge* normal = new edge(a, b, flow, cap);
    edge* reverse = normal->rev = new edge(b, a, 0, 0, normal);
    graph[a].push_back(normal);
    graph[b].push_back(reverse);
    return normal;
  }
  bool bfs(void) {
    distances.assign(n, INF);
    distances[sink] = 0;
    std::queue<long long> order;
    order.push(sink);
    while (!order.empty()) {
      long long best = order.front();
      order.pop();
      if (best == source) return true;
      for (edge* neigh : graph[best]) {
        if (neigh->rev->cap > neigh->rev->flow &&
            distances[neigh->b] > 1 + distances[best]) {
          distances[neigh->b] = 1 + distances[best];
          order.push(neigh->b);
        }
      }
    }
    return false;
  }
  long long dfs(const long long& pos, const long long& min) {
    if (pos == sink) {
      return min;
    }
    long long flow = 0;
    for (edge* e : graph[pos]) {
      long long curr = 0;
      if (!blocked[e->b] && distances[e->b] == distances[pos] - 1 &&
          e->cap > e->flow) {
        curr = dfs(e->b, std::min(min - flow, e->cap - e->flow));
        e->flow += curr;
        e->rev->flow = -(e->flow);
        flow += curr;
      }
      if (flow == min) return flow;
    }
    blocked[pos] = flow != min;
    return flow;
  }
  long long flow(void) {
    for (auto& row : graph) {
      for (edge* e : row) e->flow = 0;
    }
    long long ret = 0;
    while (bfs()) {
      blocked.assign(blocked.size(), false);
      ret += dfs(source, INF);
    }
    return ret;
  }
};
struct bg_scayger {
  long long r, c;
  long long t;
} boys[485], girls[485];
const long long INF2 = 0x3f3f3f3f3f3f;
const long long MAX_BOIS = 22 * 22 + 7;
long long n, m, males, females;
std::string grid[22];
long long mat[MAX_BOIS][MAX_BOIS];
DinicFlow::edge* edges[2][MAX_BOIS][MAX_BOIS];
long long get_coord(const long long& row, const long long& col) {
  return row * m + col;
}
void sub(bg_scayger* arr, const long long& len) {
  for (long long i = 0; i < len; ++i) {
    --arr[i].r;
    --arr[i].c;
  }
}
void floyd_warshall(void) {
  const long long all = n * m;
  memset(mat, 0x3f, sizeof(mat));
  for (long long i = 0; i < all; ++i) mat[i][i] = 0;
  for (long long i = 0; i < n; ++i)
    for (long long j = 0; j + 1 < m; ++j)
      if (grid[i][j] != '#' && grid[i][j + 1] != '#') {
        const long long tmp_a = get_coord(i, j), tmp_b = get_coord(i, j + 1);
        mat[tmp_a][tmp_b] = mat[tmp_b][tmp_a] = 1;
      }
  for (long long j = 0; j < m; ++j)
    for (long long i = 0; i + 1 < n; ++i)
      if (grid[i][j] != '#' && grid[i + 1][j] != '#') {
        const long long tmp_a = get_coord(i, j), tmp_b = get_coord(i + 1, j);
        mat[tmp_a][tmp_b] = mat[tmp_b][tmp_a] = 1;
      }
  for (long long k = 0; k < all; ++k)
    for (long long i = 0; i < all; ++i)
      for (long long j = i + 1; j < all; ++j)
        if (mat[i][k] < INF2 && mat[k][j] < INF2)
          mat[i][j] = mat[j][i] = std::min(
              mat[i][j], static_cast<long long>(mat[i][k] + mat[k][j]));
}
bool doit(const long long& limit, DinicFlow& myflow) {
  for (long long loc = 0; loc < n * m; ++loc) {
    for (long long i = 0; i < males; ++i) {
      const long long boi = get_coord(boys[i].r, boys[i].c);
      const long long gur = get_coord(girls[i].r, girls[i].c);
      if (mat[loc][boi] < INF2) {
        edges[0][i][loc]->cap = (boys[i].t * mat[loc][boi]) <= limit;
      } else {
        edges[0][i][loc]->cap = 0;
      }
      if (mat[loc][gur] < INF2) {
        edges[1][i][loc]->cap = (girls[i].t * mat[loc][gur]) <= limit;
      } else {
        edges[1][i][loc]->cap = 0;
      }
    }
  }
  return myflow.flow() >= males;
}
int main(void) {
  std::cin >> n >> m >> males >> females;
  for (long long i = 0; i < n; ++i) std::cin >> grid[i];
  if (std::abs(males - females) != 1) {
    std::cout << "-1\n";
    return 0;
  }
  if (males < females)
    std::cin >> boys[males].r >> boys[males].c >> boys[males].t;
  else
    std::cin >> girls[females].r >> girls[females].c >> girls[females].t;
  for (long long i = 0; i < males; ++i)
    std::cin >> boys[i].r >> boys[i].c >> boys[i].t;
  for (long long i = 0; i < females; ++i)
    std::cin >> girls[i].r >> girls[i].c >> girls[i].t;
  if (males < females)
    ++males;
  else
    ++females;
  assert(males == females);
  sub(boys, males);
  sub(girls, females);
  floyd_warshall();
  DinicFlow myflow(males + females + n * m + n * m);
  for (long long i = 0; i < males; ++i) {
    myflow.add_edge(myflow.source, i, 1);
    myflow.add_edge(males + i, myflow.sink, 1);
  }
  for (long long loc = 0; loc < n * m; ++loc) {
    myflow.add_edge(males + females + loc, males + females + n * m + loc, 1);
    for (long long i = 0; i < males; ++i) {
      edges[0][i][loc] = myflow.add_edge(i, males + females + loc, 1);
      edges[1][i][loc] =
          myflow.add_edge(males + females + n * m + loc, males + i, 1);
    }
  }
  long long lo = 0, hi = 5e16;
  while (lo < hi) {
    const long long mid = lo + (hi - lo) / 2;
    if (doit(mid, myflow)) {
      if (!doit(mid - 1, myflow)) {
        lo = hi = mid;
        break;
      }
      hi = mid - 1;
    } else {
      lo = mid + 1;
    }
  }
  if (lo >= static_cast<long long>(5e16)) lo = -1;
  std::cout << lo << "\n";
  return 0;
}
