#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
const int MAXN = 10005;
const int INF = 0x3f3f3f3f;
int total; //邊的總數量
int s, t; //源點、匯點
int head[MAXN];
int dep[MAXN];
int cur[MAXN];
struct Edge
{
int u, v, w, next;
}edge[MAXN];
void addEdge(int u, int v, int w)
{
edge[total] = Edge{ u,v,w,head[u] };
head[u] = total++;
edge[total] = Edge{ v,u,0,head[v] };
head[v] = total++;
}
bool BFS()
{
memset(dep, 0, sizeof(dep));
dep[s] = 1;
queue<int> q;
q.push(s);
while (!q.empty())
{
int u = q.front();
q.pop();
for (int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].v;
int w = edge[i].w;
if (w > 0 && dep[v] == 0)
{
dep[v] = dep[u] + 1;
q.push(v);
}
}
}
return dep[t] != 0;
}
int DFS(int u, int flow)
{
if (u == t)
return flow;
for (int i = cur[u]; i != -1; i = edge[i].next)
{
int v = edge[i].v;
int w = edge[i].w;
if (dep[v] == dep[u] + 1 && w != 0)
{
int dis = DFS(v, min(w, flow));
if (dis > 0)
{
edge[i].w -= dis;
edge[i ^ 1].w += dis;
return dis;
}
}
}
return 0;
}
int dinic()
{
int ans = 0;
while (BFS())
{
for (int i = 0; i <= t; i++)
cur[i] = head[i];
while (int d = DFS(s, INF))
ans += d;
}
return ans;
}
int main()
{
int n, m;
while (scanf("%d%d", &n, &m) != EOF)
{
memset(head, -1, sizeof(head));
total = 0;
s = n * m;
t = n * m + 1;
int sum = 0; //所有點的數之和
int num;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
scanf("%d", &num);
if ((i + j) % 2)
{
addEdge(s, i * m + j, num);
if (i > 0)
addEdge(i * m + j, (i - 1) * m + j, INF);
if (i < n - 1)
addEdge(i * m + j, (i + 1) * m + j, INF);
if (j > 0)
addEdge(i * m + j, i * m + j - 1, INF);
if (j < m - 1)
addEdge(i * m + j, i * m + j + 1, INF);
}
else
addEdge(i * m + j, t, num);
sum += num;
}
}
int ans = dinic();
printf("%d\n", sum - ans);
}
return 0;
}