#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;   }