/*
TASK:apple
LANG:C++
*/
#include <algorithm>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <set>
#include <map>
#define PB push_back
#define MP make_pair
#define X first
#define Y second

const int TLE=0.495*CLOCKS_PER_SEC;

using namespace std;

int n,m,a[71][71],a1[71][71],g[71][71],c[71][71],g1[71][71];
struct yey{ int ax,ay,bx,by,d; };

inline bool operator<(yey x,yey y)
{    if (x.d!=y.d) return y.d<x.d;
     if (x.ax!=y.ax) return y.ax>x.ax;
     if (x.ay!=y.ay) return y.ay>x.ay;
     if (x.bx!=y.bx) return y.bx>x.bx;
     return y.by>x.by;
}

inline yey MY(int ax,int ay,int bx,int by,int d)
{
    yey a;
    a.ax=ax;
    a.bx=bx;
    a.ay=ay;
    a.by=by;
    a.d=d;
    return a;
}

const int mv[4][4]=
{
{0,1,1,0},
{1,0,0,1},
{1,0,1,0},
{0,1,0,1}
};

map<int,int> d[128][128][128];

int greedy(int y,int x)
{
     if (y<1 || y>n || x<1 || x>m) return 0;
     if (g[y][x]<1000000) return g[y][x];
     else { g[y][x]=max(greedy(y-1,x),greedy(y,x-1))+a1[y][x];
            if (g[y-1][x]>g[y][x-1]) c[y][x]=0; else c[y][x]=1;
            return g[y][x]; }
}

int main()
{
    int i,j,k,l;
//    ifstream f("apple.in"); 
    scanf("%d %d",&n,&m);
//    f>>n>>m;
    for (i=1; i<=n; i++)
     for (j=1; j<=m; j++)
       { scanf("%d",&a[i][j]); a1[i][j]=a[i][j]; g[i][j]=1000000; }
//    f.close();
    
    yey t,t1; int x1,y1,x2,y2,d1;

    g[1][1]=a[1][1];    
    g[n][m]=greedy(n,m); l=g[n][m];
    i=n; j=m;
    while (j>1 || i>1)
    {
     a1[i][j]=0;
     if (c[i][j]==1 && j>1) j--; else i--;
    } 
    
    for (i=1; i<=n; i++)
     for (j=1; j<=m; j++) 
      { g[i][j]=1000000; g1[i][j]=g[i][j]; }
    g[1][1]=0; 
    g[n][m]=greedy(n,m); l+=g[n][m];
    
    set<yey> q;
    d[1][1][1][1]=a[1][1];
    q.insert(MY(1,1,1,1,a[1][1]));
    while (!q.empty())
    {
          t=*q.begin();
          q.erase(q.begin());
//          cout<<t.ax<<" "<<t.ay<<" "<<t.bx<<" "<<t.by<<" "<<t.d<<" "<<j<<" "<<q1.size()<<endl;
          for (i=0; i<4; i++)
           if (t.ax+mv[i][0]<=m && t.ay+mv[i][1]<=n && t.bx+mv[i][2]<=m && t.by+mv[i][3]<=n)
            {
               x1=t.ax+mv[i][0]; y1=t.ay+mv[i][1]; x2=t.bx+mv[i][2]; y2=t.by+mv[i][3];
               if (x1==x2 && y1==y2) d1=a[y1][x1];
               else d1=a[y1][x1]+a[y2][x2];
               if (x1>x2 || (x1==x2 && y1>y2))
                {
                 swap(x1,x2);
                 swap(y2,y1);
                }
               if (t.d+d1>d[y1][x1][y2][x2] && (t.d+d1>=g[y1][x1]+g1[y2][x2] || t.d+d1>=g[y2][x2]+g[y1][x1]))
               {
                  q.insert(MY(x1,y1,x2,y2,t.d+d1));
                  d[y1][x1][y2][x2]=t.d+d1;
               }
            }
       if (clock()>TLE) break;
    }
    
//    cout<<k<<endl;
//    cout<<max(d[n][m][n][m],l)<<"\n";
    printf("%d\n",max(d[n][m][n][m],l));
    
    return 0;
}
