// vvvvvvvvvvvv TEMPLATE vvvvvvvvvvvv
#include <bits/stdc++.h>
using namespace std; using ll = long long; using P = pair<ll, ll>;
const ll linf = 1e18; const double eps = 1e-12, pi = acos(-1);
#define FOR(i,a,b) for (ll i=(a),__last_##i=(b);i<__last_##i;i++)
#define RFOR(i,a,b) for (ll i=(b)-1,__last_##i=(a);i>=__last_##i;i--)
#define REP(i,n) FOR(i,0,n)
#define RREP(i,n) RFOR(i,0,n)
#define __GET_MACRO3(_1, _2, _3, NAME, ...) NAME
#define each(i,a) for (auto&& i : a)
#define rep(...) __GET_MACRO3(__VA_ARGS__, FOR, REP)(__VA_ARGS__)
#define rrep(...) __GET_MACRO3(__VA_ARGS__, RFOR, RREP)(__VA_ARGS__)
#define pb push_back
#define eb emplace_back
#define all(a) begin(a),end(a)
#define chmin(x,v) x = min(x, v)
#define chmax(x,v) x = max(x, v)
template<typename T> ll min(ll a, const T&& b) { return a < b ? a : b; }
template<typename T> ll min(const T&& a, ll b) { return a < b ? a : b; }
template<typename T> ll max(ll a, const T&& b) { return a > b ? a : b; }
template<typename T> ll max(const T&& a, ll b) { return a > b ? a : b; }
template<typename Head> void out(Head h) { cout << h << endl; } template<typename Head, typename... Tail>void out(Head h, Tail... t) { cout << h << " "; out(t...); }
template<typename T> istream& operator>>(istream& is, vector<T>& v) { each(x,v) is >> x; return is; }
template<typename T> ostream& operator<<(ostream& os, const vector<T>& v) { rep(i,v.size()) { if (i) os << " "; os << v[i]; } return os; }
ostream& operator<<(ostream& os, const vector<string>& v) { rep(i,v.size()) { if (i) os << endl; os << v[i]; } return os; }
template<typename T> ostream& operator<<(ostream& os, const vector<vector<T>>& v) { rep(i,v.size()) { if (i) os << endl; os << v[i]; } return os; }
template<typename T1, typename T2> ostream& operator<<(ostream& os, const pair<T1, T2>& p) { return os << "(" << p.first << ", " << p.second << ")"; }
struct yes_no : std::numpunct<char> { string_type do_truename() const { return "Yes"; } string_type do_falsename() const { return "No"; } };
void solve(); int main() {
  ios::sync_with_stdio(false); cin.tie(0); locale loc(locale(), new yes_no); cout.imbue(loc); cout << fixed << setprecision(10) << boolalpha;
  solve();
}
// ^^^^^^^^^^^^ TEMPLATE ^^^^^^^^^^^^

class MaxFlow {
public:
  struct Edge {
    ll to, cap, rev;
  };
  vector<vector<Edge>> G;
  vector<ll> iter;
private:
  bool is_debug;
  ll V;
  vector<ll> bfs(ll s) {
    vector<ll> dist(V, linf);
    dist[s] = 0;
    queue<ll> Q; Q.push(s);
    while ( !Q.empty() ) {
      ll v = Q.front(); Q.pop();
      each(e, G[v]) {
        if (e.cap > 0 && dist[e.to] == linf) {
          dist[e.to] = dist[v]+1;
          Q.push(e.to);
        }
      }
    }
    return dist;
  }
  ll dfs(ll v, ll t, ll f, const vector<ll>& dist, vector<bool>& used) {
    if (v == t) return f;
    if (used[v]) return 0;
    used[v] = true;
    for (ll& i = iter[v]; i < G[v].size(); ++i) {
      Edge& e = G[v][i];
      if (e.cap > 0 && dist[e.to] == dist[v]+1) {
        ll d = dfs(e.to, t, min(f, e.cap), dist, used);
        if (d > 0) {
          e.cap -= d;
          G[e.to][e.rev].cap += d;
          return d;
        }
      }
    }
    return 0;
  }
public:
  const vector<vector<Edge>>& Graph() {
    return G;
  }
  MaxFlow(ll V, bool is_debug=false) : V(V), G(V), is_debug(is_debug) {}
  void init(ll n) {
    V = n;
    G.assign(V, vector<Edge>());
  }
  void add(ll from, ll to, ll cap) {
    if (is_debug) cout << "ADD: " << from << " " << to << " " << cap << endl;
    assert(V > 0);
    G[from].pb({to, cap, (ll)G[to].size()});
    G[to].pb({from, 0, (ll)G[from].size()-1});
  }
  // S -> s, T -> t に inf は自力で
  void add(ll from, ll to, ll min_flow, ll cap, ll S, ll T) {
    if (is_debug) cout << endl << "ADD_MIN:" << from << " " << to << " " << min_flow << " " << cap << endl;
    add(from, to, cap-min_flow);
    add(S, to, min_flow);
    add(from, T, cap);
    if (is_debug) cout << endl;
  }
  ll flow(ll s, ll t, ll f=linf) {
    ll res = 0;
    while (f > 0) {
      vector<ll> dist = bfs(s);
      if (dist[t] == linf) break;
      iter.assign(G.size(), 0);
      while (f > 0) {
        vector<bool> used(V, false);
        ll df = dfs(s, t, f, dist, used);
        if (df == 0) break;
        f -= df;
        res += df;
      }
    }
    return res;
  }
};

ll dx1[] = {-1, 1, -1, 1};
ll dy1[] = {-1, -1, 1, 1};
ll dx2[] = {0, 1, 0, 1};
ll dy2[] = {0, 0, 1, 1};

void solve() {
  ll h, w, W; cin >> h >> w >> W;
  vector<vector<ll>> A(h, vector<ll>(w)); cin >> A;
  ll nxt_id = 0;
  vector<vector<ll>> bid(h-1, vector<ll>(w-1, -1));
  rep(y, h-1) rep(x, w-1) {
    if ((x + y) % 2 == 0) {
      bid[y][x] = nxt_id++;
    }
  }
  ll s = nxt_id++;
  ll t = nxt_id++;
  MaxFlow mf(t+1);
  ll sum = 0;
  rep(y, h) rep(x, w) {
    sum += A[y][x];
  }
  auto isBorder = [&](ll x, ll y) {
    return x == 0 || x == w-1 || y == 0 || y == h-1;
  };
  rep(y, h-1) rep(x, w-1) {
    if ((x + y) % 2) continue;
    if (x % 2 == 0) {
      mf.add(bid[y][x], t, W);
      rep(d, 4) {
        ll nx1 = x + dx1[d], ny1 = y + dy1[d];
        ll nx2 = x + dx2[d], ny2 = y + dy2[d];
        if (isBorder(nx2, ny2)) {
          mf.add(s, bid[y][x], A[ny2][nx2]);
        }
        else {
          assert(bid[ny1][nx1] >= 0);
          mf.add(bid[ny1][nx1], bid[y][x], A[ny2][nx2]);
        }
      }
    }
    else {
      mf.add(s, bid[y][x], W);
      rep(d, 4) {
        ll nx1 = x + dx1[d], ny1 = y + dy1[d];
        ll nx2 = x + dx2[d], ny2 = y + dy2[d];
        if (isBorder(nx2, ny2)) {
          mf.add(bid[y][x], t, A[ny2][nx2]);
        }
      }
    }
  }
  ll ans = sum - mf.flow(s, t);
  cout << ans << endl;
}



Measured memory_bytes: 3508