#include <bits/stdc++.h>
using namespace std;
const int maxN = 300, maxTreeSize = 1 << 10;
struct Tree {
 private:
  bool active[maxTreeSize];
  int Min[maxTreeSize], Max[maxTreeSize], offset;

 public:
  void resize(int n) {
    offset = 1;
    while (offset < n) offset *= 2;
  }
  void add(int v, int val) {
    v += offset;
    active[v] = true;
    Min[v] = Max[v] = val;
    while (v > 1) {
      v /= 2;
      active[v] = true;
      if (active[v * 2] and active[v * 2 + 1]) {
        Min[v] = min(Min[v * 2], Min[v * 2 + 1]);
        Max[v] = max(Max[v * 2], Max[v * 2 + 1]);
      } else if (active[v * 2]) {
        Min[v] = Min[v * 2];
        Max[v] = Max[v * 2];
      } else {
        Min[v] = Min[v * 2 + 1];
        Max[v] = Max[v * 2 + 1];
      }
    }
  }
  pair<int, int> query(int val) {
    int v = 1;
    while (v < offset) {
      if (!active[v * 2] or !active[v * 2 + 1]) {
        v = active[v * 2] ? v * 2 : v * 2 + 1;
        continue;
      }
      if (val <= Max[v * 2]) {
        v = v * 2;
        continue;
      }
      if (Min[v * 2 + 1] <= val) {
        v = v * 2 + 1;
        continue;
      }
      int diff1 = abs(Max[v * 2] - val), diff2 = abs(Min[v * 2 + 1] - val);
      v = (diff1 <= diff2) ? v * 2 : v * 2 + 1;
    }
    return make_pair(v - offset, abs(val - Max[v]));
  }
  void clear() {
    for (int i = 1; i < offset * 2; i++) active[i] = false;
  }
};
int sumpUp[maxN + 1][maxN + 1], sumpDown[maxN + 1][maxN + 1],
    sumpLeft[maxN + 1][maxN + 1], sumpRight[maxN + 1][maxN + 1],
    sump1[maxN + 1], sump2[maxN + 1], T[maxN + 1][maxN + 1];
int tp, tu, td, ord_in_tree[maxN + 1];
pair<int, int> temp[maxN];
int cost_of_step(int a, int b) {
  if (a == b) return tp;
  if (a < b) return tu;
  if (a > b) return td;
}
Tree tree;
int main() {
  int n, m, ts;
  scanf("%d%d%d%d%d%d", &n, &m, &ts, &tp, &tu, &td);
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= m; j++) scanf("%d", &T[i][j]);
  }
  for (int i = 1; i <= n; i++) {
    for (int j = 2; j <= m; j++)
      sumpLeft[i][j] = sumpLeft[i][j - 1] + cost_of_step(T[i][j - 1], T[i][j]);
    for (int j = m - 1; j > 0; j--)
      sumpRight[i][j] =
          sumpRight[i][j + 1] + cost_of_step(T[i][j + 1], T[i][j]);
  }
  for (int j = 1; j <= m; j++) {
    for (int i = 2; i <= n; i++)
      sumpUp[i][j] = sumpUp[i - 1][j] + cost_of_step(T[i - 1][j], T[i][j]);
    for (int i = n - 1; i > 0; i--)
      sumpDown[i][j] = sumpDown[i + 1][j] + cost_of_step(T[i + 1][j], T[i][j]);
  }
  tree.resize(m);
  int min_diff = 1000000000;
  int i1, j1, i2, j2;
  for (int a = 1; a <= n; a++) {
    for (int b = a + 2; b <= n; b++) {
      for (int j = 1; j <= m; j++) {
        sump1[j] = sumpLeft[a][j] + (sumpUp[b][j] - sumpUp[a][j]) +
                   sumpRight[b][1] - sumpRight[b][j];
        sump2[j] = sumpLeft[a][j] - (sumpDown[a][j] - sumpDown[b][j]) +
                   (sumpRight[b][1] - sumpRight[b][j]);
        temp[j - 1] = make_pair(sump2[j], j);
      }
      sort(temp, temp + m);
      for (int j = 0; j < m; j++) ord_in_tree[temp[j].second] = j;
      tree.add(ord_in_tree[1], sump2[1]);
      for (int j = 3; j <= m; j++) {
        pair<int, int> res_temp = tree.query(sump1[j] - ts);
        if (res_temp.second < min_diff) {
          min_diff = res_temp.second;
          i1 = a;
          j1 = temp[res_temp.first].second;
          i2 = b;
          j2 = j;
        }
        tree.add(ord_in_tree[j - 1], sump2[j - 1]);
      }
      tree.clear();
    }
  }
  printf("%d %d %d %d\n", i1, j1, i2, j2);
  return 0;
}
