#include <bits/stdc++.h>
using namespace std;
struct edge {
  int id;
  int x, y;
  long long int w;
  edge(int id, int x, int y, long long int w) : id(id), x(x), y(y), w(w) {}
};
struct edge2 {
  int viz;
  int cap;
  int dual;
  edge2(int viz, int cap, int dual) : viz(viz), cap(cap), dual(dual) {}
};
int dx[] = {0, -1, 0, 1};
int dy[] = {1, 0, -1, 0};
long long int d[25][25];
char grid[25][25];
vector<edge> v;
vector<edge2> g[2005];
int n, m;
int flow;
int s, t;
int male_id;
int fem_id;
int p[2005];
int p_edge[2005];
int d2[2005];
bool comp(const struct edge &a, const struct edge &b) { return a.w < b.w; }
void inline BFS(int sx, int sy, int id, int cost) {
  int x, y;
  int nx, ny;
  queue<pair<int, int> > fila;
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      d[i][j] = 10000000000000000LL;
    }
  }
  d[sx][sy] = 0;
  fila.push(make_pair(sx, sy));
  while (!fila.empty()) {
    x = fila.front().first;
    y = fila.front().second;
    fila.pop();
    for (int i = 0; i < 4; i++) {
      nx = x + dx[i];
      ny = y + dy[i];
      if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
        if (grid[nx][ny] != '#' && d[nx][ny] > d[x][y] + cost) {
          d[nx][ny] = d[x][y] + cost;
          fila.push(make_pair(nx, ny));
        }
      }
    }
  }
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      if (d[i][j] != 10000000000000000LL) {
        v.push_back(edge(id, i, j, d[i][j]));
      }
    }
  }
  return;
}
int inline BFS2(int s, int t) {
  int next;
  int viz;
  int cap;
  queue<int> fila;
  memset(d2, 0x3f3f3f3f, sizeof(d2));
  d2[s] = 0;
  fila.push(s);
  while (!fila.empty()) {
    next = fila.front();
    fila.pop();
    for (int i = 0; i < (int)g[next].size(); i++) {
      viz = g[next][i].viz;
      cap = g[next][i].cap;
      if (cap && d2[viz] > d2[next] + 1) {
        d2[viz] = d2[next] + 1;
        p[viz] = next;
        p_edge[viz] = i;
        fila.push(viz);
      }
    }
  }
  return d2[t] != 0x3f3f3f3f;
}
void inline add_edge(int x, int y, int cap) {
  g[x].push_back(edge2(y, cap, (int)g[y].size()));
  g[y].push_back(edge2(x, 0, (int)g[x].size() - 1));
  return;
}
void max_flow(int s, int t) {
  int augment;
  int dual;
  int cap;
  int idx;
  while (BFS2(s, t)) {
    augment = 0x3f3f3f3f;
    for (int v = t; v != s; v = p[v]) {
      idx = p_edge[v];
      cap = g[p[v]][idx].cap;
      augment = min(augment, g[p[v]][idx].cap);
    }
    for (int v = t; v != s; v = p[v]) {
      idx = p_edge[v];
      dual = g[p[v]][idx].dual;
      g[p[v]][idx].cap -= augment;
      g[v][dual].cap += augment;
    }
    flow += augment;
  }
  return;
}
void build_graph(void) {
  int idx, idx2;
  for (int i = 2 * 22 * 22 + 1; i < male_id; i++) {
    add_edge(s, i, 1);
  }
  for (int i = male_id; i < fem_id; i++) {
    add_edge(i, t, 1);
  }
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      if (grid[i][j] != '#') {
        idx = 22 * i + j;
        idx2 = 22 * 22 + idx;
        add_edge(idx, idx2, 1);
      }
    }
  }
  return;
}
int main(void) {
  int male, fem;
  int x, y, z;
  int idx;
  long long int best;
  int ok = 0;
  int next_group;
  int size;
  scanf(" %d %d %d %d", &n, &m, &male, &fem);
  for (int i = 0; i < n; i++) {
    scanf(" %s", grid[i]);
  }
  if (male == fem || abs(male - fem) > 1) {
    printf("-1\n");
  } else {
    scanf(" %d %d %d", &x, &y, &z);
    x--;
    y--;
    male_id = 2 * 22 * 22 + 1;
    fem_id = 2 * 22 * 22 + 1 + male;
    if (male < fem) {
      fem_id++;
      BFS(x, y, male_id++, z);
    } else {
      BFS(x, y, fem_id++, z);
    }
    for (int i = 0; i < male; i++) {
      scanf(" %d %d %d", &x, &y, &z);
      x--;
      y--;
      BFS(x, y, male_id++, z);
    }
    for (int i = 0; i < fem; i++) {
      scanf(" %d %d %d", &x, &y, &z);
      x--;
      y--;
      BFS(x, y, fem_id++, z);
    }
    if (fem < male) {
      fem++;
    }
    sort(v.begin(), v.end(), comp);
    size = (int)sqrt((int)v.size());
    s = fem_id;
    t = fem_id + 1;
    build_graph();
    best = -1;
    flow = 0;
    next_group = 0;
    for (int i = 0; (i + 1) * size < (int)v.size(); i++) {
      next_group = i + 1;
      for (int j = i * size; j < (i + 1) * size; j++) {
        idx = 22 * v[j].x + v[j].y;
        if (v[j].id < male_id) {
          add_edge(v[j].id, idx, 1);
        } else {
          idx = 22 * 22 + idx;
          add_edge(idx, v[j].id, 1);
        }
      }
      max_flow(s, t);
      if (flow == fem) {
        ok = 1;
        break;
      }
    }
    if (!ok) {
      for (int i = next_group * size; i < (int)v.size(); i++) {
        idx = 22 * v[i].x + v[i].y;
        if (v[i].id < male_id) {
          add_edge(v[i].id, idx, 1);
        } else {
          idx = 22 * 22 + idx;
          add_edge(idx, v[i].id, 1);
        }
        max_flow(s, t);
        if (flow == fem) {
          best = v[i].w;
          break;
        }
      }
    } else {
      flow = 0;
      for (int i = 0; i <= t; i++) {
        g[i].clear();
      }
      build_graph();
      for (int i = 0; i < (next_group - 1) * size; i++) {
        idx = 22 * v[i].x + v[i].y;
        if (v[i].id < male_id) {
          add_edge(v[i].id, idx, 1);
        } else {
          idx = 22 * 22 + idx;
          add_edge(idx, v[i].id, 1);
        }
      }
      for (int i = (next_group - 1) * size; i < (int)v.size(); i++) {
        idx = 22 * v[i].x + v[i].y;
        if (v[i].id < male_id) {
          add_edge(v[i].id, idx, 1);
        } else {
          idx = 22 * 22 + idx;
          add_edge(idx, v[i].id, 1);
        }
        max_flow(s, t);
        if (flow == fem) {
          best = v[i].w;
          break;
        }
      }
    }
    printf("%lld\n", best);
  }
  return 0;
}
