#include<bits/stdc++.h>
#define ll long long
#define i128 __int128
#define ull unsigned long long
#define pii pair<int,int>
#define pll pair<long long, long long>
#define fs first
#define sc second
#define x0 _x0_
#define y1 _y1_
#define endl '\n'
#define re register
#define pb push_back
#define vi vector<int>
#define pq priority_queue
#define mem(a,x) memset((a),(x),sizeof(a))
#define debug puts("AK IOI")
#define sz(s) (int)(s.size())
#define all(a) a.begin(),a.end()
#define rd(l,r) (myrand()%(r-l+1)+l)
#define print(x) {cout<<x<<endl;return;}
#define For(x,y,z) for(int x = y;x <= z;x++)
#define For_(x,y,z) for(int x = y;x >= z;x--)
#define between(x, flo, top) (flo <= x && x <= top)
#define id(i, j) ((i - 1) * m + j)
using namespace std;
#define int long long
const int mod = 1e9+7;
mt19937 myrand(time(0));
const int inf = 0x3f3f3f3f,N = 1e4+5,M = 1e6+5,K = 3000+5;
const long long linf = 0x3f3f3f3f3f3f3f3f;
namespace FastIO {template <typename T = int>inline T read() {T s=0,w=1;char c=getchar();while(!isdigit(c)){if(c=='-')w=-1;c=getchar();}while(isdigit(c))s=(s<<1)+(s<<3)+(c^48),c=getchar();return s*w;}template <typename T>inline void read(T &s){s=0;int w=1;char c=getchar();while(!isdigit(c)){if(c=='-')w=-1;c=getchar();}while(isdigit(c))s=(s<<1)+(s<<3)+(c^48),c=getchar();s*=w;}template <typename T, typename... Args> inline void read(T &x, Args &...args) {read(x), read(args...);}template <typename T>inline void write(T x,char ch = '\n') {if(x<0)x=-x,putchar('-');static char stk[200];int top=0;do{stk[top++]=x%10+'0',x/=10;}while(x);while(top)putchar(stk[--top]);putchar(ch);return;}}
using namespace FastIO;
int s,t;
namespace maxflow{
int dist[N],tot=1,now[N],head[N];
const int inf = 0x3f3f3f3f3f3f3f3f;
struct node{
int to,nxt,val;
}edge[N];
void add(int u,int v,int w){
edge[++tot].to=v,edge[tot].val=w,edge[tot].nxt=head[u],head[u]=tot;
edge[++tot].to=u,edge[tot].val=0,edge[tot].nxt=head[v],head[v]=tot;
}bool bfs(){
memset(dist,0x3f,sizeof dist);
queue<int> q;q.push(s);dist[s]=0,now[s]=head[s];
while(!q.empty()){
int f=q.front();q.pop();
for(int i=head[f];i;i=edge[i].nxt){
int to = edge[i].to;
if(edge[i].val > 0&& dist[to]==inf){
q.push(to),now[to]=head[to],dist[to]=dist[f]+1;
if(to==t) return true;
}
}
}return false;
}int dfs(int x,int sum){
if(x==t) return sum;
int k=0;
int res=0;
for(int i = now[x];i && sum;i=edge[i].nxt){
now[x]=i;
int to = edge[i].to;
if(edge[i].val && (dist[to] == dist[x] + 1)){
k=dfs(to,min(sum,edge[i].val));
if(!k) dist[to] = inf;
edge[i].val-=k,edge[i^1].val+=k;
res+=k,sum-=k;
}
}return res;
}int dinic(){
int ans=0;
while(bfs()) ans += dfs(s,inf);
return ans;
}
}using namespace maxflow;
namespace direction{
int dx[4]={0,0,-1,1},dy[4]={1,-1,0,0};
}using namespace direction;
int n,m;
int a[N][N];
void solve(){
int sum=0;
cin>>n>>m;
t=n*m+1;
For(i,1,n)For(j,1,m)cin>>a[i][j];
For(i,1,n)For(j,1,m){
sum += a[i][j];
if(!((i+j)&1)){
add(s,id(i,j),a[i][j]);
For(k,0,3){
int xx=i+dx[k],yy=j+dy[k];
if(between(xx,1,n) && between(yy,1,m)){
add(id(i,j),id(xx,yy),linf);
}
}
}else{
add(id(i,j),t,a[i][j]);
}
}
cout<<sum-dinic();
}signed main(){
solve();
return 0;
}