#include<iostream>
#include<cstdio>
#include<cstring>
#include<deque>
using namespace std;
const int MAXN=6233,MAXM=233333,SHIFT=3000;
struct edge
{
int v,f,w;
edge *next,*rev;
}*h[MAXN],pool[MAXM*2];
int top;
inline void addedge(int u,int v,int c,int w)
{
edge *tmp=&pool[top++];tmp->v=v;tmp->f=c;tmp->w=w;tmp->next=h[u];h[u]=tmp;
edge *pmt=&pool[top++];pmt->v=u;pmt->f=0;pmt->w=-w;pmt->next=h[v];h[v]=pmt;
tmp->rev=pmt;pmt->rev=tmp;
}
inline int Hash(int i,int j){return (i-1)*50+j-1;}
deque<int> q;
int S,T;
int last[MAXN],inq[MAXN];
long long dis[MAXN],maxf[MAXN];
edge *laste[MAXN];
long long totcost,totflow;
bool SPFA()
{
memset(dis,0x3f,sizeof(dis));
memset(last,0,sizeof(last));
memset(maxf,0,sizeof(maxf));
memset(inq,0,sizeof(inq));
while(!q.empty())q.pop_front();
q.push_front(S);
maxf[S]=0x3f3f3f3f3f3f3f3fll;
inq[S]=1;
dis[S]=0;
while(!q.empty())
{
int u=q.front();q.pop_front();
inq[u]=0;
for(edge *tmp=h[u];tmp;tmp=tmp->next)
{
if(tmp->f&&dis[tmp->v]>dis[u]+tmp->w)
{
dis[tmp->v]=dis[u]+tmp->w;
last[tmp->v]=u;
maxf[tmp->v]=max(maxf[tmp->v],min(maxf[u],(long long)tmp->f));
laste[tmp->v]=tmp;
if(!inq[tmp->v])
{
if(q.empty()||dis[q.front()]>tmp->v)q.push_front(tmp->v);
else q.push_back(tmp->v);
inq[tmp->v]=1;
}
}
}
}
if(dis[T]>=0x3f3f3f3f3f3f3f3fll)return false;
int u=T;
while(last[u])
{
laste[u]->f-=maxf[T];
laste[u]->rev->f+=maxf[T];
u=last[u];
}
totcost+=dis[T]*maxf[T];
totflow+=maxf[T];
return true;
}
int n,m;
int mat[55][55];
int main()
{
scanf("%d%d",&m,&n);
S=Hash(1,1)+SHIFT,T=Hash(m,n);
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
scanf("%d",&mat[i][j]);
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
{
if(i!=m)addedge(Hash(i,j)+SHIFT,Hash(i+1,j),1,0);
if(j!=n)addedge(Hash(i,j)+SHIFT,Hash(i,j+1),1,0);
addedge(Hash(i,j),Hash(i,j)+SHIFT,1,-mat[i][j]);
}
while(SPFA());
printf("%lld\n",-totcost);
return 0;
}
QWQ