#include <bits/stdc++.h>
const int INF = 0x7f7f7f7f;
const int maxn = 11111;
const int mod = 1000000000;
const double eps = 1e-10;
int head[maxn], e;
int q[maxn << 6], front, rear;
bool inq[maxn];
int pre[maxn], cur[maxn], dis[maxn];
struct node {
  int cap, cost, v, next;
  node() {}
  node(int cap, int cost, int v, int next)
      : cap(cap), cost(cost), v(v), next(next) {}
} edge[maxn << 6];
void add_edge(int u, int v, int c, int cc, int cost) {
  edge[e] = node(c, cost, v, head[u]);
  head[u] = e++;
  edge[e] = node(cc, -cost, u, head[v]);
  head[v] = e++;
}
int spfa(int s, int t, int n) {
  int i, u, v;
  for (i = 0; i <= n; ++i) dis[i] = INF;
  front = rear = 0;
  dis[s] = 0;
  pre[s] = s;
  cur[s] = -1;
  q[rear++] = s;
  while (front < rear) {
    u = q[front++];
    inq[u] = false;
    for (i = head[u]; ~i; i = edge[i].next) {
      v = edge[i].v;
      if (edge[i].cap > 0 && dis[u] + edge[i].cost < dis[v]) {
        dis[v] = dis[u] + edge[i].cost;
        pre[v] = u;
        cur[v] = i;
        if (!inq[v]) {
          inq[v] = true;
          q[rear++] = v;
        }
      }
    }
  }
  return dis[t];
}
int minx(int a, int b) { return (a == -1 || b < a) ? b : a; }
int MinCost(int s, int t, int n) {
  int ans = 0, u, v, cap, cost, flow = 0;
  while (true) {
    cost = spfa(s, t, n);
    if (cost == INF) break;
    u = v = t;
    cap = -1;
    for (u = pre[u]; v != s; v = u, u = pre[u]) {
      cap = minx(cap, edge[cur[v]].cap);
    }
    ans += cost * cap;
    flow += cap;
    u = v = t;
    for (u = pre[u]; v != s; v = u, u = pre[u]) {
      edge[cur[v]].cap -= cap;
      edge[cur[v] ^ 1].cap += cap;
    }
  }
  return ans;
}
int dx[] = {0, 1, 0, -1};
int dy[] = {1, 0, -1, 0};
int a[85][85];
int num[85][85];
int n, m;
bool ok(int x, int y) { return (x >= 1 && x <= n && y >= 1 && y <= m); }
int main() {
  int i, j, k, x, y, u, v;
  scanf("%d%d", &n, &m);
  for (i = 1; i <= n; ++i)
    for (j = 1; j <= m; ++j) scanf("%d", a[i] + j);
  k = 0;
  for (i = 1; i <= n; ++i)
    for (j = 1; j <= m; ++j) num[i][j] = ++k;
  int src = 0, dest = n * m + 1;
  memset(head, -1, sizeof(head));
  for (i = 1; i <= n; ++i) {
    for (j = 1; j <= m; ++j) {
      u = num[i][j];
      if ((i + j) & 1) {
        add_edge(src, u, 1, 0, 0);
        for (k = 0; k < 4; ++k) {
          x = i + dx[k];
          y = j + dy[k];
          if (!ok(x, y)) continue;
          v = num[x][y];
          add_edge(u, v, 1, 0, a[i][j] != a[x][y]);
        }
      } else
        add_edge(u, dest, 1, 0, 0);
    }
  }
  int res = MinCost(src, dest, dest + 1);
  printf("%d\n", res);
  return 0;
}
