#include <bits/stdc++.h>
using namespace std;
const int N = 6666, INF = 0x3f3f3f3f;
struct MCMF {
  int s, t, vis[N], d[N], head[N], cur[N], etot;
  struct edge {
    int v, cap, cost, next;
  } g[555555];
  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 aug(int u, int a) {
    if (u == t) return a;
    vis[u] = 1;
    for (int &i = cur[u]; i != -1; i = g[i].next) {
      edge &e = g[i];
      if (e.cap && !vis[e.v] && d[u] == d[e.v] + e.cost)
        if (int tmp = aug(e.v, min(a, e.cap))) {
          e.cap -= tmp;
          g[i ^ 1].cap += tmp;
          return tmp;
        }
    }
    return 0;
  }
  bool modlabel() {
    int tmp = INF;
    for (int u = 0; u < N; u++)
      if (vis[u]) {
        for (int i = head[u]; i != -1; i = g[i].next) {
          edge &e = g[i];
          if (e.cap && !vis[e.v]) tmp = min(tmp, d[e.v] + e.cost - d[u]);
        }
      }
    if (tmp == INF) return true;
    assert(tmp <= 1);
    for (int u = 0; u < N; u++)
      if (vis[u]) {
        vis[u] = 0;
        d[u] += tmp;
      }
    return false;
  }
  int min_cost_flow(int _s, int _t) {
    s = _s;
    t = _t;
    int cost = 0, tmp;
    while (true) {
      memcpy(cur, head, sizeof(head));
      while (tmp = aug(s, INF)) {
        cost += tmp * d[s];
        memset(vis, 0, sizeof(vis));
      }
      if (modlabel()) break;
    }
    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;
}
