#include <bits/stdc++.h>
using namespace std;
const int N = 666, INF = 0x3f3f3f3f;
struct MCMF {
  int s, t, dis[N], prevv[N], preve[N], inq[N], head[N], etot;
  struct edge {
    int v, cap, cost, next;
  } g[5555];
  void add_edge(int u, int v, int cap, int cost) {
    g[etot] = (edge){v, cap, cost, head[u]};
    head[u] = etot++;
    g[etot] = (edge){u, 0, -cost, head[v]};
    head[v] = etot++;
  }
  void init() {
    memset(head, -1, sizeof(head));
    etot = 0;
  }
  int min_cost_flow(int _s, int _t) {
    s = _s;
    t = _t;
    int cost = 0;
    while (true) {
      memset(dis, INF, sizeof(dis));
      dis[s] = 0;
      prevv[s] = preve[s] = -1;
      queue<int> que;
      que.push(s);
      while (!que.empty()) {
        int u = que.front();
        que.pop();
        inq[u] = 0;
        for (int i = head[u]; i != -1; i = g[i].next) {
          edge &e = g[i];
          if (e.cap && dis[e.v] > dis[u] + e.cost) {
            dis[e.v] = dis[u] + e.cost;
            prevv[e.v] = u;
            preve[e.v] = i;
            if (!inq[e.v]) que.push(e.v), inq[e.v] = 1;
          }
        }
      }
      if (dis[t] == INF) break;
      int d = INF;
      for (int v = t; v != s; v = prevv[v]) {
        edge &e = g[preve[v]];
        d = min(d, e.cap);
      }
      cost += d * dis[t];
      for (int v = t; v != s; v = prevv[v]) {
        g[preve[v]].cap -= d;
        g[preve[v] ^ 1].cap += d;
      }
    }
    return cost;
  }
} F;
int n, m, G[110][110], dir[4][2] = {0, 1, 1, 0, 0, -1, -1, 0};
int main() {
  scanf("%d%d", &n, &m);
  for (int i = 0; i < n; i++)
    for (int j = 0; j < m; j++) scanf("%d", &G[i][j]);
  int _s = n * m, _t = _s + 1;
  F.init();
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      if ((i + j & 1) == 1)
        F.add_edge(i * m + j, _t, 1, 0);
      else {
        F.add_edge(_s, i * m + j, 1, 0);
        for (int k = 0; k < 4; k++) {
          int ex = i + dir[k][0];
          int ey = j + dir[k][1];
          if (ex < 0 || ex >= n || ey < 0 || ey >= m) continue;
          F.add_edge(i * m + j, ex * m + ey, 1, G[i][j] != G[ex][ey]);
        }
      }
    }
  }
  printf("%d\n", F.min_cost_flow(_s, _t));
  return 0;
}
