#include <bits/stdc++.h>
using namespace std;
long long mod = (1000000007LL);
inline long long poww(long long a, long long b) {
  long long res = 1;
  while (b > 0) {
    if (b & 1) res = (res * a) % mod;
    a = (a * a) % mod;
    b >>= 1;
  }
  return res;
}
inline pair<int, int> operator+(pair<int, int> A, pair<int, int> B) {
  return pair<int, int>(A.first + B.first, A.second + B.second);
}
inline pair<int, int> operator-(pair<int, int> A, pair<int, int> B) {
  return pair<int, int>(A.first - B.first, A.second - B.second);
}
inline long long mult(long long a, long long b) { return (a * b) % mod; }
long long gcd(long long a, long long b) {
  while (b) {
    a %= b;
    swap(a, b);
  }
  return a;
}
int n, m, q, k, v[55], ans;
pair<int, int> TT, w[55];
int mat[55][20005], pref[55][20005], L[55][20005], R[55][20005];
int dp[55][20005];
string second;
struct segt {
  int tree[4 * 20005];
  void clear() { memset(tree, 0, sizeof tree); }
  void upd(int nod, int a, int b, int i, int x) {
    if (a == b) {
      tree[nod] = x;
    } else {
      if (i <= ((a + b) / 2))
        upd((2 * nod), a, ((a + b) / 2), i, x);
      else
        upd((2 * nod + 1), ((a + b) / 2) + 1, b, i, x);
      tree[nod] = max(tree[(2 * nod)], tree[(2 * nod + 1)]);
    }
  }
  int query(int nod, int a, int b, int i, int j) {
    if (j < a or i > b or i > j) return -2000000000;
    if (i <= a and j >= b) return tree[nod];
    return max(query((2 * nod), a, ((a + b) / 2), i, j),
               query((2 * nod + 1), ((a + b) / 2) + 1, b, i, j));
  }
} T[2];
int32_t main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cin >> n >> m >> k;
  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= m; j++) {
      cin >> mat[i][j];
      pref[i][j] = mat[i][j] + pref[i][j - 1];
    }
  T[0].clear(), T[1].clear();
  for (int dia = n; dia >= 1; dia--) {
    for (int l = 1; l <= m - k + 1; l++) {
      int r = l + k - 1;
      int cost = pref[dia][r] - pref[dia][l - 1] + pref[dia + 1][r] -
                 pref[dia + 1][l - 1];
      dp[dia][l] =
          max((l >= k ? L[dia + 1][l - k] : 0), R[dia + 1][r + 1]) + cost;
      int meio1 = (T[0].query(1, 1, m, max(1, l - k + 1), l - 1) +
                   pref[dia + 1][l - 1] + cost);
      int meio2 =
          (T[1].query(1, 1, m, l, min(r, m - k + 1)) - pref[dia + 1][r] + cost);
      dp[dia][l] = max({dp[dia][l], meio1, meio2});
    }
    T[0].clear();
    T[1].clear();
    for (int l = 1; l <= m - k + 1; l++)
      L[dia][l] = max(dp[dia][l], L[dia][l - 1]);
    for (int l = m; l >= 1; l--) {
      R[dia][l] = max(dp[dia][l], R[dia][l + 1]);
      T[0].upd(1, 1, m, l, dp[dia][l] - pref[dia][l + k - 1]);
      T[1].upd(1, 1, m, l, dp[dia][l] + pref[dia][l - 1]);
    }
  }
  int ans = 0;
  for (int l = 1; l <= m - k + 1; l++) {
    ans = max(ans, dp[1][l]);
  }
  cout << ans << "\n";
}
