#include <bits/stdc++.h>
using namespace std;
const double PI = acos(-1.0);
const int INF = 1000000000;
const int MAXN = 10000;
struct Edge {
  int b, back;
  int c, u, f;
};
class MCMF {
 private:
  int n;
  vector<Edge> g[MAXN];
  int *from, *from_edge, *d, *phi, *state, *q;
  bool *used;

 public:
  MCMF(int _n) {
    n = _n;
    from = new int[n];
    from_edge = new int[n];
    d = new int[n];
    state = new int[n];
    q = new int[n];
    phi = new int[n];
    for (int i = 0; i < (int)(n); i++) phi[i] = 0;
    used = new bool[n];
  }
  void addEdge(int a, int b, int cap, int cost) {
    Edge e1 = {b, int((g[b]).size()), cost, cap, 0};
    Edge e2 = {a, int((g[a]).size()), -cost, 0, 0};
    g[a].push_back(e1);
    g[b].push_back(e2);
  }
  void levit(int s) {
    int qh, qt;
    qh = 0, qt = 0;
    for (int i = 0; i < (int)(n); i++) state[i] = 2, d[i] = INF;
    memset(from, -1, sizeof(from));
    state[s] = 1;
    q[qh++] = s;
    d[s] = 0;
    while (qh != qt) {
      int v = q[qt++];
      qt %= n;
      state[v] = 0;
      for (int i = 0; i < (int)(int((g[v]).size())); i++)
        if (g[v][i].f < g[v][i].u && d[g[v][i].b] > d[v] + g[v][i].c) {
          int to = g[v][i].b;
          d[to] = d[v] + g[v][i].c;
          from[to] = v;
          from_edge[to] = i;
          if (state[to] == 1) continue;
          if (state[to] == 0) {
            qt--;
            if (qt == -1) qt = n - 1;
            q[qt] = to;
            state[to] = 1;
          } else {
            state[to] = 1;
            q[qh++] = to;
            qh %= n;
          }
        }
    }
  }
  pair<int, int> getMaxFlow(int s, int t) {
    int flow = 0;
    int cost = 0;
    while (true) {
      levit(s);
      for (int i = 0; i < n; i++) phi[i] += d[i];
      if (d[t] == INF) break;
      int it = t;
      int addflow = INF;
      while (it != s) {
        addflow = min(addflow, g[from[it]][from_edge[it]].u -
                                   g[from[it]][from_edge[it]].f);
        it = from[it];
      }
      it = t;
      while (it != s) {
        g[from[it]][from_edge[it]].f += addflow;
        g[it][g[from[it]][from_edge[it]].back].f -= addflow;
        cost += g[from[it]][from_edge[it]].c * addflow;
        it = from[it];
      }
      flow += addflow;
    }
    return make_pair(flow, cost);
  }
};
int R, C;
const int maxR = 80;
const int maxC = 80;
int t[maxR][maxC];
int main() {
  cin >> R >> C;
  for (int r = 0; r < (int)(R); r++)
    for (int c = 0; c < (int)(C); c++) cin >> t[r][c];
  MCMF mcmf(1 + R * C + 1);
  int dr[] = {0, 1, 0, -1};
  int dc[] = {-1, 0, 1, 0};
  for (int r = 0; r < (int)(R); r++) {
    for (int c = 0; c < (int)(C); c++)
      if ((r + c) % 2) {
        mcmf.addEdge(0, 1 + r * C + c, 1, 0);
        for (int i = 0; i < (int)(4); i++) {
          int nr = r + dr[i];
          int nc = c + dc[i];
          if (0 <= nr && nr < R && 0 <= nc && nc < C) {
            mcmf.addEdge(1 + r * C + c, 1 + nr * C + nc, 1,
                         t[r][c] != t[nr][nc]);
          }
        }
      } else {
        mcmf.addEdge(1 + r * C + c, 1 + R * C, 1, 0);
      }
  }
  pair<int, int> res = mcmf.getMaxFlow(0, 1 + R * C);
  long long flow = res.first;
  long long cost = res.second;
  assert(res.first == (R * C) / 2);
  cout << res.second << endl;
  return 0;
}
