#include<iostream>
#include<algorithm>
#include<limits>
#include<queue>
using ll=long long;
const int sz=110;
const ll inf=std::numeric_limits<ll>::max();
struct edge{
int nxt,to;
ll w;
}graph[sz*sz<<3];
int head[sz*sz],chead[sz*sz],hpp=1;
void addEdge(int from,int to,ll w){
graph[++hpp]=edge{head[from],to,w};
head[from]=hpp;
}
int dep[sz],n,m,s,t;
bool bfs(){
std::queue<int>qq;
std::fill(dep,dep+n*m+2,0);
std::copy(head,head+n*m+2,chead);
qq.push(s),dep[s]=1;
while(!qq.empty()){
int u=qq.front();
qq.pop();
for(int p=head[u];p;p=graph[p].nxt){
int v=graph[p].to;
if(dep[v]==0&&graph[p].w!=0)qq.push(v),dep[v]=dep[u]+1;
}
}
return dep[t]!=0;
}
ll dfs(int u,ll lim){
if(u==t||lim==0)return lim;
ll arc=0,path=0;
for(int p=chead[u];p&&lim;p=graph[p].nxt){
chead[u]=p;
int v=graph[p].to;
if(dep[v]==dep[u]+1&&graph[p].w!=0){
arc=dfs(v,std::min(lim,graph[p].w));
path+=arc,lim-=arc;
graph[p].w-=arc,graph[p^1].w+=arc;
}
}
return path;
}
ll dinic(){
ll ans=0;
while(bfs())ans+=dfs(s,inf);
return ans;
}
int id[sz][sz],cpp,dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};
int main(){
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cin>>n>>m,t=n*m+1;
ll sum=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)id[i][j]=++cpp;
for(int i=1;i<=n;i++){
for(int j=1,k;j<=m;j++){
std::cin>>k,sum+=k;
if(i+j&1){
addEdge(0,id[i][j],k),addEdge(id[i][j],0,0);
for(int p=0;p<4;p++){
int x=i+dx[p],y=j+dy[p];
if(x<1||x>n||y<1||y>m)continue;
addEdge(id[i][j],id[x][y],inf),addEdge(id[x][y],id[i][j],0);
}
}else addEdge(id[i][j],t,k),addEdge(t,id[i][j],0);
}
}
std::cout<<sum-dinic()<<"\n";
return 0;
}