#include <queue>
#include <cstdio>
#include <iostream>
using namespace std;
struct ColorNode {
int x,y;
bool color;
};
struct EdgeType {
int v,f,e;
};
struct EdgeType edge[900000];
const int dx[5]={0,-1,0,1,0};
const int dy[5]={0,0,1,0,-1};
int n,m,dis[50][50],ans,head[1001],s=0,t;
int cnt=1,deep[1001];
bool if_[50][50];
char Cget;
inline void in(int &now)
{
now=0,Cget=getchar();
while(Cget>'9'||Cget<'0') Cget=getchar();
while(Cget>='0'&&Cget<='9')
{
now=now*10+Cget-'0';
Cget=getchar();
}
}
struct ColorNode node(int x,int y,int color)
{
struct ColorNode pos;
pos.x=x,pos.y=y,pos.color=color;
return pos;
}
inline void edge_add(int u,int v,int f)
{
edge[++cnt].v=v,edge[cnt].f=f,edge[cnt].e=head[u],head[u]=cnt;
edge[++cnt].v=u,edge[cnt].f=0,edge[cnt].e=head[v],head[v]=cnt;
}
bool BFS()
{
queue<int>que;
for(int i=s;i<=t;i++) deep[i]=-1;
deep[s]=0;que.push(s);
while(!que.empty())
{
int pos=que.front();que.pop();
for(int i=head[pos];i;i=edge[i].e)
{
if(deep[edge[i].v]<0&&edge[i].f>0)
{
deep[edge[i].v]=deep[pos]+1;
if(edge[i].v==t) return true;
que.push(edge[i].v);
}
}
}
return false;
}
int flowing(int now,int flow)
{
if(now==t||flow<=0) return flow;
int oldflow=0;
for(int i=head[now];i;i=edge[i].e)
{
if(edge[i].f<=0||deep[edge[i].v]!=deep[now]+1) continue;
int pos=flowing(edge[i].v,min(edge[i].f,flow));
flow-=pos;
oldflow+=pos;
edge[i].f-=pos;
edge[i^1].f+=pos;
if(flow==0) return oldflow;
}
return oldflow;
}
int main()
{
freopen("grid.in","r",stdin);
freopen("grid.out","w",stdout);
in(n),in(m);t=n*m+1;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
in(dis[i][j]);
ans+=dis[i][j];
}
}
queue<ColorNode>que;
if_[1][1]=true;
que.push(node(1,1,if_[1][1]));
while(!que.empty())
{
struct ColorNode pos=que.front();que.pop();
if(pos.color)
{
edge_add(s,(pos.x-1)*m+pos.y,dis[pos.x][pos.y]);
int x=pos.x,y=pos.y,hash=(pos.x-1)*m+pos.y;
for(int i=1;i<=4;i++)
{
if(x+dx[i]>0&&x+dx[i]<=n&&y+dy[i]>0&&y+dy[i]<=m)
{
edge_add(hash,(pos.x+dx[i]-1)*m+pos.y+dy[i],0x7ffffff);
}
}
}
else edge_add((pos.x-1)*m+pos.y,t,dis[pos.x][pos.y]);
if(pos.x+1<=n&&!if_[pos.x+1][pos.y])
{
que.push(node(pos.x+1,pos.y,!pos.color));
if_[pos.x+1][pos.y]=true;
}
if(pos.y+1<=m&&!if_[pos.x][pos.y+1])
{
if_[pos.x][pos.y+1]=true;
que.push(node(pos.x,pos.y+1,!pos.color));
}
}
while(BFS()) ans-=flowing(s,0x7ffffff);
cout<<ans;
return 0;
}