#include <bits/stdc++.h>
using namespace std;
using ll = long long;
template <class T, class U>
using Pa = pair<T, U>;
template <class T>
using vec = vector<T>;
template <class T>
using vvec = vector<vec<T>>;
constexpr int inf = 1e9;
template <typename Monoid, typename F>
class SegmentTree {
 private:
  int sz;
  vector<Monoid> seg;
  const F op;
  const Monoid e;

 public:
  SegmentTree(int n, const F op, const Monoid &e) : op(op), e(e) {
    sz = 1;
    while (sz <= n) sz <<= 1;
    seg.assign(2 * sz, e);
  }
  void set(int k, const Monoid &x) { seg[k + sz] = x; }
  void build() {
    for (int i = sz - 1; i > 0; i--) {
      seg[i] = op(seg[2 * i], seg[2 * i + 1]);
    }
  }
  void update(int k, const Monoid &x) {
    k += sz;
    seg[k] = x;
    while (k >>= 1) {
      seg[k] = op(seg[2 * k], seg[2 * k + 1]);
    }
  }
  Monoid query(int l, int r) {
    Monoid L = e, R = e;
    for (l += sz, r += sz; l < r; l >>= 1, r >>= 1) {
      if (l & 1) L = op(L, seg[l++]);
      if (r & 1) R = op(seg[--r], R);
    }
    return op(L, R);
  }
  Monoid operator[](const int &k) const { return seg[k + sz]; }
};
void chmax(int &a, int b) {
  if (a < b) a = b;
}
int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  int N, M, K;
  cin >> N >> M >> K;
  vvec<int> A(N, vec<int>(M));
  vvec<int> S(N + 1, vec<int>(M + 1, 0));
  for (int i = 0; i < N; i++)
    for (int j = 0; j < M; j++) {
      cin >> A[i][j];
      S[i][j + 1] = S[i][j] + A[i][j];
    }
  vvec<int> dp(N + 1, vec<int>(M + 1, -inf));
  fill(dp[0].begin(), dp[0].end(), 0);
  vvec<int> maL(N + 1, vec<int>(M + 1, 0)), maR(N + 1, vec<int>(M + 1, 0));
  auto op = [](int a, int b) { return max(a, b); };
  SegmentTree<int, decltype(op)> segL(M, op, -inf), segR(M, op, -inf);
  auto sum = [&](int i, int l, int r) { return S[i][min(r, M)] - S[i][l]; };
  for (int i = 0; i < N; i++) {
    for (int j = 0; j < M; j++) {
      int ne_s = (i != N - 1 ? sum(i + 1, j, j + K) : 0), s = sum(i, j, j + K);
      if (j - K + 1 >= 0) {
        chmax(dp[i + 1][j], maL[i][j - K + 1] + s);
      }
      if (j + K <= M) {
        chmax(dp[i + 1][j], maR[i][j + K] + s);
      }
      chmax(dp[i + 1][j], segL.query(max(j - K + 1, 0), j) + sum(i, 0, j + K));
      chmax(dp[i + 1][j], segR.query(j, min(j + K, M)) - sum(i, 0, j));
      dp[i + 1][j] += ne_s;
    }
    for (int j = 0; j < M; j++) {
      maL[i + 1][j + 1] = max(maL[i + 1][j], dp[i + 1][j]);
      segL.set(j, dp[i + 1][j] - sum(i + 1, 0, j + K));
    }
    for (int j = M - 1; j >= 0; j--) {
      maR[i + 1][j] = max(maR[i + 1][j + 1], dp[i + 1][j]);
      segR.set(j, dp[i + 1][j] + sum(i + 1, 0, j));
    }
    segL.build();
    segR.build();
  }
  cout << *max_element(dp[N].begin(), dp[N].end()) << "\n";
}
