#include <bits/stdc++.h>
using namespace std;
namespace mincostflow {
struct edge {
  int to, cap, cost, rev;
  edge(int to = 0, int cap = 0, int cost = 0, int rev = 0)
      : to(to), cap(cap), cost(cost), rev(rev) {}
};
vector<edge> g[7000];
int dist[7000], q[7000 * 2];
int frome[7000], fromv[7000];
bool inq[7000];
int s, t;
void add_edge(int from, int to, int cap, int cost) {
  g[from].push_back(edge(to, cap, cost, g[to].size()));
  g[to].push_back(edge(from, 0, -cost, g[from].size() - 1));
}
bool dij() {
  for (int i = 0; i <= t; i++) dist[i] = 1000000000;
  dist[s] = 0;
  q[0] = s;
  inq[s] = 1;
  int head = 0, tail = 1;
  while (head != tail) {
    int now = q[head++];
    if (head == 7000 + 1) head = 0;
    for (int i = 0; i < g[now].size(); i++) {
      edge &e = g[now][i];
      if (e.cap && dist[e.to] > dist[now] + e.cost) {
        dist[e.to] = dist[now] + e.cost;
        frome[e.to] = i;
        fromv[e.to] = now;
        if (!inq[e.to]) {
          if (dist[e.to] < dist[q[head]]) {
            head--;
            if (head == -1) head = 7000;
            q[head] = e.to;
          } else {
            q[tail++] = e.to;
            if (tail == 7000 + 1) tail = 0;
          }
        }
      }
    }
    inq[now] = 0;
  }
  return dist[t] != 1000000000;
}
int augment() {
  int c = 1000000000, ret = 0;
  for (int i = t; i != s; i = fromv[i]) c = min(c, g[fromv[i]][frome[i]].cap);
  for (int i = t; i != s; i = fromv[i]) {
    edge &e = g[fromv[i]][frome[i]];
    ret += c * e.cost;
    e.cap -= c;
    g[e.to][e.rev].cap += c;
  }
  return ret;
}
int mcf() {
  int ans = 0;
  while (dij()) ans += augment();
  return ans;
}
};  // namespace mincostflow
int a[100][100];
int id[100][100];
int n, m, cnt;
int main() {
  using namespace mincostflow;
  scanf("%d%d", &n, &m);
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= m; j++) {
      scanf("%d", &a[i][j]);
      id[i][j] = ++cnt;
    }
  }
  s = ++cnt;
  t = ++cnt;
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= m; j++) {
      if ((i + j) & 1)
        add_edge(s, id[i][j], 1, 0);
      else
        add_edge(id[i][j], t, 1, 0);
    }
  }
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= m; j++) {
      if ((i + j) % 2 == 0) continue;
      if (id[i][j - 1])
        add_edge(id[i][j], id[i][j - 1], 1, (a[i][j] != a[i][j - 1]));
      if (id[i][j + 1])
        add_edge(id[i][j], id[i][j + 1], 1, (a[i][j] != a[i][j + 1]));
      if (id[i - 1][j])
        add_edge(id[i][j], id[i - 1][j], 1, (a[i][j] != a[i - 1][j]));
      if (id[i + 1][j])
        add_edge(id[i][j], id[i + 1][j], 1, (a[i][j] != a[i + 1][j]));
    }
  }
  printf("%d\n", mcf());
  return 0;
}
