#include <bits/stdc++.h>
using namespace std;
struct SegTree {
  int sz, *dat, *laz;
  SegTree() {
    sz = 1 << 17;
    dat = new int[sz << 1];
    laz = new int[sz << 1];
    memset(dat, 0, sz << 3);
    memset(laz, 0, sz << 3);
  }
  SegTree(const int &n) {
    sz = 1;
    while (sz < n) sz <<= 1;
    dat = new int[sz << 1];
    laz = new int[sz << 1];
    memset(dat, 0, sz << 3);
    memset(laz, 0, sz << 3);
  }
  ~SegTree() {
    delete[] dat;
    delete[] laz;
  }
  void upd(int id, int l, int r, int ql, int qr, int val) {
    if (qr < l || r < ql) return;
    if (ql <= l && r <= qr) {
      laz[id] = max(laz[id], val);
      dat[id] = max(dat[id], val);
      return;
    }
    laz[id << 1] = max(laz[id << 1], laz[id]);
    dat[id << 1] = max(dat[id << 1], laz[id]);
    laz[id << 1 | 1] = max(laz[id << 1 | 1], laz[id]);
    dat[id << 1 | 1] = max(dat[id << 1 | 1], laz[id]);
    laz[id] = 0;
    upd(id << 1, l, l + r >> 1, ql, qr, val);
    upd(id << 1 | 1, (l + r >> 1) + 1, r, ql, qr, val);
    dat[id] = min(dat[id << 1], dat[id << 1 | 1]);
  }
  int qry(int id, int l, int r, int ql, int qr) {
    if (qr < l || r < ql) return 1e9;
    if (ql <= l && r <= qr) {
      return dat[id];
    }
    laz[id << 1] = max(laz[id << 1], laz[id]);
    dat[id << 1] = max(dat[id << 1], laz[id]);
    laz[id << 1 | 1] = max(laz[id << 1 | 1], laz[id]);
    dat[id << 1 | 1] = max(dat[id << 1 | 1], laz[id]);
    laz[id] = 0;
    return min(qry(id << 1, l, l + r >> 1, ql, qr),
               qry(id << 1 | 1, (l + r >> 1) + 1, r, ql, qr));
  }
  void upd(const int &l, const int &r, const int &val) {
    upd(1, 1, sz, l, r, val);
  }
  int qry(const int &l, const int &r) { return qry(1, 1, sz, l, r); }
};
int n, m, x, y, a[1005][1005];
long long ans;
map<int, int> mp;
void solve_horizonal() {
  for (int i = 1; i <= n; i++) {
    int mx = 0;
    for (int j = 1; j <= n; j++) {
      ans += max(0, a[i][j] - mx);
      mx = max(mx, a[i][j]);
    }
  }
  printf("%lld\n", ans);
}
void solve_vertical() {
  for (int j = 1; j <= n; j++) {
    int mx = 0;
    for (int i = 1; i <= n; i++) {
      ans += max(0, a[i][j] - mx);
      mx = max(mx, a[i][j]);
    }
  }
  printf("%lld\n", ans);
}
int main() {
  scanf("%d%d%d", &n, &x, &y);
  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= n; j++) {
      scanf("%d", a[n - j + 1] + i);
    }
  if (x < 0) {
    x = -x;
    for (int i = 1; i <= n; i++)
      for (int j = 1; j <= n >> 1; j++) {
        swap(a[i][j], a[i][n - j + 1]);
      }
  }
  if (y > 0) {
    for (int i = 1; i <= n >> 1; i++)
      for (int j = 1; j <= n; j++) {
        swap(a[n - i + 1][j], a[i][j]);
      }
  } else
    y = -y;
  swap(x, y);
  if (x == 0) {
    solve_horizonal();
    return 0;
  }
  if (y == 0) {
    solve_vertical();
    return 0;
  }
  for (int i = 0; i <= n; i++)
    for (int j = 0; j <= n; j++) {
      mp[i * y + j * x] = 0;
    }
  for (pair<const int, int> &p : mp) p.second = ++m;
  SegTree st(m - 1);
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= n; j++) {
      ans = ans + max(0, a[i][j] - st.qry(mp[(n - i) * y + (j - 1) * x],
                                          mp[(n - i + 1) * y + j * x] - 1));
      st.upd(mp[(n - i) * y + (j - 1) * x], mp[(n - i + 1) * y + j * x] - 1,
             a[i][j]);
    }
  }
  printf("%lld\n", ans);
  return 0;
}
