#include <bits/stdc++.h>
using namespace std;
using llong = long long;
using vi = vector<int>;
using vvi = vector<vi>;
using vvvi = vector<vvi>;
using pii = pair<int, int>;
constexpr int INF = 1e9;
constexpr double EPS = 1e-9;
constexpr int MOD = 1e9 + 7;
template <class Type>
void line(const Type &a) {
  int cnt = 0;
  for (const auto &elem : a) {
    cerr << (cnt++ ? ' ' : '>');
    cerr << elem;
  }
  cerr << endl;
}
using vl = vector<long long>;
using vvl = vector<vl>;
using vvvl = vector<vvl>;
const int dy[] = {0, 1};
const int dx[] = {1, 0};
template <typename T, typename U>
struct PrimalDual {
  using P = pair<U, int>;
  struct Edge {
    int to;
    T cap;
    U cost;
    int rev;
  };
  int vn;
  vector<vector<Edge> > g;
  vector<U> h;
  vector<U> dist;
  vi prevv, preve;
  U inf;
  PrimalDual(unsigned int vn_)
      : vn(vn_), g(vn_), h(vn_), dist(vn_), prevv(vn_), preve(vn_) {
    if (typeid(U) == typeid(int))
      inf = 1e9;
    else if (typeid(U) == typeid(long long))
      inf = 1e18;
  }
  void add_egde(int from, int to, T cap, U cost) {
    g[from].push_back((Edge){to, cap, cost, (int)g[to].size()});
    g[to].push_back((Edge){from, 0, -cost, (int)g[from].size() - 1});
  }
  U min_cost_flow(int s, int t, T f) {
    U res = 0;
    fill((h).begin(), (h).end(), 0);
    while (f > 0) {
      fill((dist).begin(), (dist).end(), inf);
      dist[s] = 0;
      priority_queue<P, vector<P>, greater<P> > pque;
      pque.push(P(0, s));
      while (!pque.empty()) {
        P p = pque.top();
        pque.pop();
        int v = p.second;
        if (dist[v] < p.first) continue;
        for (int i = 0; i < (g[v].size()); ++i) {
          Edge &e = g[v][i];
          if (e.cap > 0 and dist[e.to] > dist[v] + e.cost + h[v] - h[e.to]) {
            dist[e.to] = dist[v] + e.cost + h[v] - h[e.to];
            prevv[e.to] = v;
            preve[e.to] = i;
            pque.push(P(dist[e.to], e.to));
          }
        }
      }
      if (dist[t] == inf) return -1;
      for (int v = 0; v < (vn); ++v) h[v] += dist[v];
      int d = f;
      for (int v = t; v != s; v = prevv[v])
        d = min(d, g[prevv[v]][preve[v]].cap);
      f -= d;
      res += d * h[t];
      for (int v = t; v != s; v = prevv[v]) {
        Edge &e = g[prevv[v]][preve[v]];
        e.cap -= d;
        g[v][e.rev].cap += d;
      }
    }
    return res;
  }
};
int main() {
  int h, w;
  cin >> h >> w;
  vvl a(h, vl(w));
  for (int i = 0; i < (h); ++i)
    for (int j = 0; j < (w); ++j) cin >> a[i][j];
  PrimalDual<int, llong> ob(2 * h * w + 2);
  ob.add_egde(2 * h * w, 0, 1, -a[0][0]);
  ob.add_egde(2 * h * w, 0, 1, 0);
  ob.add_egde(h * w - 1, 2 * h * w + 1, 1, 0);
  ob.add_egde(2 * h * w - 1, 2 * h * w + 1, 1, 0);
  auto jud = [&](const int y, const int x) -> bool {
    return (0 <= y and y < h and 0 <= x and x < w);
  };
  for (int i = 0; i < (h); ++i)
    for (int j = 0; j < (w); ++j) {
      for (int k = 0; k < (2); ++k) {
        int ny = i + dy[k], nx = j + dx[k];
        if (jud(ny, nx)) {
          for (int ii = 0; ii < (2); ++ii)
            for (int jj = 0; jj < (2); ++jj) {
              if (jj == 0)
                ob.add_egde(i * w + j + ii * h * w, ny * w + nx + jj * h * w, 1,
                            -a[ny][nx]);
              else
                ob.add_egde(i * w + j + ii * h * w, ny * w + nx + jj * h * w, 1,
                            0);
            }
        }
      }
    }
  cout << -ob.min_cost_flow(2 * h * w, 2 * h * w + 1, 2) << endl;
  return 0;
}
