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

 public:
  MCMF(int _s, int _t, int _n) {
    s = _s;
    t = _t;
    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 < (n); ++i) phi[i] = 0;
    used = new bool[n];
  }
  void addEdge(int a, int b, int c, int u) {
    Edge e1 = {b, c, u, 0, int((g[b]).size())};
    Edge e2 = {a, -c, 0, 0, int((g[a]).size())};
    g[a].push_back(e1);
    g[b].push_back(e2);
  }
  void levit() {
    int qh, qt;
    qh = 0, qt = 0;
    for (int i = (0); i < (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((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;
          }
        }
    }
  }
  void dijkstra() {
    memset(used, true, sizeof(used));
    used[s] = false;
    for (int i = (0); i < (n); ++i) d[i] = INF;
    d[s] = 0;
    while (true) {
      int v = -1;
      for (int i = 0; i < n; i++) {
        if (!used[i] && (v == -1 || d[v] > d[i])) v = i;
      }
      if (v == -1) break;
      used[v] = true;
      for (int i = (0); i < (int((g[v]).size())); ++i)
        if (g[v][i].f < g[v][i].u) {
          int to = g[v][i].b;
          if (d[to] > d[v] + g[v][i].c + phi[v] - phi[to]) {
            d[to] = d[v] + g[v][i].c + phi[v] - phi[to];
            from[to] = v;
            from_edge[to] = i;
            used[to] = false;
          }
        }
    }
  }
  pair<int, int> minCostMaxFlow() {
    int flow = 0;
    int cost = 0;
    while (true) {
      levit();
      for (int i = 0; i < n; i++) phi[i] += d[i];
      if (d[t] == INF) break;
      int it = t;
      int addflow = FLOW_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 maxN = 82;
const int maxM = 82;
int t[maxN][maxM];
const int maxV = 82 * 82;
int dr[] = {1, 0, -1, 0};
int dc[] = {0, 1, 0, -1};
bool ok(int r, int c) { return (r >= 0 && r < R && c >= 0 && c < C); }
int key(int u, int v) { return 81 * u + v; }
int main() {
  cin >> R >> C;
  for (int i = 0; i < (int)R; i++)
    for (int j = 0; j < (int)C; j++) cin >> t[i][j];
  const int src = maxV - 1;
  const int tgt = maxV - 2;
  MCMF mcmf(src, tgt, maxV);
  for (int r = 0; r < (int)R; r++) {
    for (int c = 0; c < (int)C; c++)
      if ((r + c) % 2 == 0) {
        mcmf.addEdge(src, key(r, c), 0, 1);
        for (int d = 0; d < (int)4; d++) {
          int nr = r + dr[d];
          int nc = c + dc[d];
          if (ok(nr, nc)) {
            int cost = (t[r][c] == t[nr][nc]) ? 0 : 1;
            mcmf.addEdge(key(r, c), key(nr, nc), cost, 1);
          }
        }
      }
  }
  for (int r = 0; r < (int)R; r++)
    for (int c = 0; c < (int)C; c++)
      if ((r + c) % 2 == 1) mcmf.addEdge(key(r, c), tgt, 0, 1);
  pair<int, int> res = mcmf.minCostMaxFlow();
  int fl = res.first;
  int cst = res.second;
  assert(fl == (R * C) / 2);
  cout << cst << endl;
  return 0;
}
