#include <bits/stdc++.h>
using namespace std;
bool debug = false;
int n, m, k;
int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};
long long ln, lk, lm;
class MinCostFlow {
 public:
  int V, E;
  int cap[100000];
  int cost[100000], dist[10000], pot[10000];
  int to[100000], prev[100000], last[10000], path[10000];
  bool used[10000];
  priority_queue<pair<int, int> > q;
  MinCostFlow(int n) {
    V = n;
    E = 0;
    for (int(i) = 0; (i) < (int)(V); (i)++) last[i] = -1;
  }
  void add_edge(int x, int y, int w, int c) {
    cap[E] = w;
    cost[E] = c;
    to[E] = y;
    prev[E] = last[x];
    last[x] = E;
    E++;
    cap[E] = 0;
    cost[E] = -c;
    to[E] = x;
    prev[E] = last[y];
    last[y] = E;
    E++;
  }
  pair<int, int> search(int s, int t) {
    int ansf = 0;
    int ansc = 0;
    for (int(i) = 0; (i) < (int)(V); (i)++) used[i] = false;
    for (int(i) = 0; (i) < (int)(V); (i)++) dist[i] = (1 << 29);
    dist[s] = 0;
    path[s] = -1;
    q.push(make_pair(0, s));
    while (!q.empty()) {
      int x = q.top().second;
      q.pop();
      if (used[x]) continue;
      used[x] = true;
      for (int e = last[x]; e >= 0; e = prev[e])
        if (cap[e] > 0) {
          int tmp = dist[x] + cost[e] + pot[x] - pot[to[e]];
          if (tmp < dist[to[e]] && !used[to[e]]) {
            dist[to[e]] = tmp;
            path[to[e]] = e;
            q.push(make_pair(-dist[to[e]], to[e]));
          }
        }
    }
    for (int(i) = 0; (i) < (int)(V); (i)++) pot[i] += dist[i];
    if (used[t]) {
      ansf = (1 << 29);
      for (int e = path[t]; e >= 0; e = path[to[e ^ 1]])
        ansf = min(ansf, cap[e]);
      for (int e = path[t]; e >= 0; e = path[to[e ^ 1]]) {
        ansc += cost[e] * ansf;
        cap[e] -= ansf;
        cap[e ^ 1] += ansf;
      }
    }
    return make_pair(ansf, ansc);
  }
  pair<int, int> mincostflow(int s, int t) {
    int ansf = 0;
    int ansc = 0;
    for (int(i) = 0; (i) < (int)(V); (i)++) pot[i] = 0;
    while (1) {
      pair<int, int> p = search(s, t);
      if (!used[t]) break;
      ansf += p.first;
      ansc += p.second;
    }
    return make_pair(ansf, ansc);
  }
};
int mp[105][105];
int id(int i, int j) { return i * m + j + 1; }
int main() {
  scanf("%d%d", &n, &m);
  int s = 0, t = m * n + 10;
  MinCostFlow mcf = MinCostFlow(t + 10);
  for (int(i) = 0; (i) < (int)(n); (i)++) {
    for (int(j) = 0; (j) < (int)(m); (j)++) {
      scanf("%d", &mp[i][j]);
      if ((i + j) % 2 == 0) {
        mcf.add_edge(s, id(i, j), 1, 0);
      } else {
        mcf.add_edge(id(i, j), t, 1, 0);
      }
    }
  }
  for (int(i) = 0; (i) < (int)(n); (i)++) {
    for (int(j) = 0; (j) < (int)(m); (j)++)
      if ((i + j) % 2 == 0) {
        for (int(k) = 0; (k) < (int)(4); (k)++) {
          int x = i + dx[k], y = j + dy[k];
          if (x >= 0 && y >= 0 && x < n && y < m) {
            mcf.add_edge(id(i, j), id(x, y), 1, mp[i][j] != mp[x][y]);
          }
        }
      }
  }
  auto p = mcf.mincostflow(s, t);
  cout << p.second << endl;
  return 0;
}
