#include <bits/stdc++.h>
using namespace std;
long long rdtsc() {
  long long tmp;
  asm("rdtsc" : "=A"(tmp));
  return tmp;
}
inline int myrand() { return abs((rand() << 15) ^ rand()); }
inline int rnd(int x) { return myrand() % x; }
struct Graph {
  vector<vector<int> > es, inv, fs, ps;
  int n;
  vector<int> st, dist, pr;
  void build(int _n) {
    n = _n;
    es = inv = fs = ps = vector<vector<int> >(n);
    st = dist = pr = vector<int>(n);
  }
  void adde(int s, int t, int c, int p) {
    es[s].push_back(t), es[t].push_back(s);
    inv[s].push_back(((int)(es[t]).size()) - 1),
        inv[t].push_back(((int)(es[s]).size()) - 1);
    fs[s].push_back(c), fs[t].push_back(0);
    ps[s].push_back(p), ps[t].push_back(-p);
  }
  pair<int, int> flow(int S, int T) {
    int flow = 0;
    int cost = 0;
    while (1) {
      for (int i = 0; i < n; ++i) dist[i] = ((int)1e9), pr[i] = -1;
      st.clear();
      st.push_back(S);
      dist[S] = 0;
      for (int l = 0; l < ((int)(st).size()); ++l) {
        int v = st[l];
        for (int it = 0; it < ((int)(es[v]).size()); ++it) {
          int u = es[v][it];
          if (fs[v][it] && dist[u] > dist[v] + ps[v][it]) {
            dist[u] = dist[v] + ps[v][it];
            pr[u] = inv[v][it];
            st.push_back(u);
          }
        }
      }
      if (dist[T] == ((int)1e9)) break;
      for (int v = T; v != S;) {
        fs[v][pr[v]] += 1;
        int u = es[v][pr[v]];
        fs[u][inv[v][pr[v]]] -= 1;
        v = u;
      }
      cost += dist[T];
      ++flow;
    }
    return make_pair(flow, cost);
  }
} g;
const int maxg = 4;
const int go[maxg][2] = {{1, 0}, {-1, 0}, {0, -1}, {0, 1}};
const int maxn = 90;
int a[maxn][maxn];
int h, w;
inline bool ok(int y, int x) { return 0 <= y && 0 <= x && y < h && x < w; }
bool solve() {
  if (scanf("%d%d", &h, &w) < 2) return 0;
  for (int i = 0; i < h; ++i) {
    for (int j = 0; j < w; ++j) {
      scanf("%d", &a[i][j]);
    }
  }
  g.build(h * w + 2);
  for (int i = 0; i < h; ++i) {
    for (int j = 0; j < w; ++j) {
      if ((i + j) & 1) {
        g.adde(2 + i * w + j, 1, 1, 0);
        continue;
      }
      g.adde(0, 2 + i * w + j, 1, 0);
      for (int g = 0; g < maxg; ++g) {
        int ni = i + go[g][0], nj = j + go[g][1];
        if (!ok(ni, nj)) continue;
        ::g.adde(2 + i * w + j, 2 + ni * w + nj, 1, a[i][j] != a[ni][nj]);
      }
    }
  }
  pair<int, int> res = g.flow(0, 1);
  assert(res.first == h * w / 2);
  printf("%d\n", res.second);
  return 1;
}
int main() {
  srand(rdtsc());
  while (1) {
    if (!solve()) break;
  }
  return 0;
}
