#include <bits/stdc++.h>
const int N = 10010;
const int inf = 0x3f3f3f3f;
using namespace std;
struct dinic {
  struct node {
    int from, to, next, cap, w;
  } edge[N + 10];
  int box[N + 10], ecnt;
  void _make_map(int from, int to, int cap, int w) {
    edge[ecnt].w = w;
    edge[ecnt].to = to;
    edge[ecnt].from = from;
    edge[ecnt].cap = cap;
    edge[ecnt].next = box[from];
    box[from] = ecnt++;
  }
  void make_edge(int from, int to, int cap, int w) {
    _make_map(from, to, cap, w);
    _make_map(to, from, 0, -w);
  }
  int per[N + 10], dist[N + 10];
  bool spfa(int s, int e) {
    queue<int> que;
    bool vist[N + 10];
    memset(vist, 0, sizeof(vist));
    memset(per, -1, sizeof(per));
    for (int i = s; i <= e; i++) dist[i] = inf;
    que.push(s);
    vist[s] = 1;
    dist[s] = 0;
    while (!que.empty()) {
      int tmp = que.front();
      que.pop();
      vist[tmp] = 0;
      for (int i = box[tmp]; i + 1; i = edge[i].next) {
        if (!edge[i].cap) continue;
        if (dist[edge[i].to] == inf ||
            dist[edge[i].to] - edge[i].w > dist[tmp]) {
          dist[edge[i].to] = dist[tmp] + edge[i].w;
          per[edge[i].to] = i;
          if (!vist[edge[i].to]) {
            vist[edge[i].to] = 1;
            que.push(edge[i].to);
          }
        }
      }
    }
    return dist[e] != inf;
  }
  int min_cost(int s, int e) {
    int ans = 0, flow = inf;
    while (spfa(s, e)) {
      ans += dist[e];
      for (int i = per[e]; i + 1; i = per[edge[i].from]) {
        if (flow > edge[i].cap) flow = edge[i].cap;
      }
      for (int i = per[e]; i + 1; i = per[edge[i].from]) {
        edge[i].cap -= flow;
        edge[i ^ 1].cap += flow;
      }
    }
    return ans;
  }
  void clear() {
    memset(box, -1, sizeof(box));
    ecnt = 0;
  }
};
int n, m;
int c[4][2] = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}};
int a[110][110], cnt[110][110];
bool check(int x, int y) {
  if (x <= 0 || x > n || y <= 0 || y > m) return 0;
  return 1;
}
int main() {
  scanf("%d%d", &n, &m);
  int tmp = 0;
  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= m; j++) scanf("%d", &a[i][j]), cnt[i][j] = ++tmp;
  dinic di;
  di.clear();
  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= m; j++) {
      if ((i + j) & 1) {
        di.make_edge(0, cnt[i][j], 1, 0);
        for (int k = 0; k < 4; k++) {
          int x = i + c[k][0];
          int y = j + c[k][1];
          if (check(x, y) == 0) continue;
          di.make_edge(cnt[i][j], cnt[x][y], 1, a[i][j] != a[x][y]);
        }
      } else {
        di.make_edge(cnt[i][j], tmp + 1, 1, 0);
      }
    }
  cout << di.min_cost(0, tmp + 1) << endl;
  return 0;
}
