#include <bits/stdc++.h>
inline int in() {
  int x;
  scanf("%d", &x);
  return x;
}
using namespace std;
constexpr int inf = 1e9 + 7;
constexpr int N = 7000, O = 100000, X = 88;
int a[X][X], sh[X][X], cnt = 1, n, m;
int xx[] = {1, -1, 0, 0};
int yy[] = {0, 0, 1, -1};
int head[N], pre[O], cost[O], M = 0, cap[O], to[O];
void ad_e(int x, int y, int c, int z) {
  pre[M] = head[x];
  head[x] = M;
  to[M] = y;
  cost[M] = c;
  cap[M] = z;
  M++;
}
void add_edge(int x, int y, int c) {
  ad_e(x, y, c, 1);
  ad_e(y, x, -c, 0);
}
int dis[N], vis[N], par[N];
int spfa() {
  queue<int> Q;
  memset(dis, 63, sizeof dis);
  dis[0] = 0, par[0] = -1;
  Q.push(0);
  while ((((int)Q.size()))) {
    int x = Q.front();
    Q.pop();
    vis[x] = 0;
    for (int e = head[x]; e + 1; e = pre[e])
      if (cap[e]) {
        int y = to[e];
        if (dis[y] > (dis[x] + cost[e])) {
          dis[y] = dis[x] + cost[e];
          par[y] = e;
          if (!vis[y]) vis[y] = true, Q.push(y);
        }
      }
  }
  if (dis[1] == dis[N - 1]) return -inf;
  int i = 1, mony = 0;
  while (i) {
    int x = par[i];
    cap[x]--, cap[x ^ 1]++;
    mony += cost[x];
    i = to[x ^ 1];
  }
  return mony;
}
int max_flow() {
  int mony = 0;
  while (true) {
    int b = spfa();
    if (b == -inf) return mony;
    mony += b;
  }
}
int32_t main() {
  n = in(), m = in();
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= m; j++) {
      a[i][j] = ++cnt;
      sh[i][j] = in();
    }
  }
  memset(head, -1, sizeof head);
  memset(pre, -1, sizeof pre);
  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= m; j++) {
      if ((i + j) % 2) {
        int o = a[i][j];
        for (int k = 0; k < 4; k++)
          if (a[i + xx[k]][j + yy[k]])
            add_edge(o, a[i + xx[k]][j + yy[k]],
                     1 - (sh[i][j] == sh[i + xx[k]][j + yy[k]]));
        add_edge(0, o, 0);
      } else
        add_edge(a[i][j], 1, 0);
    }
  cout << max_flow();
}
