#include <bits/stdc++.h>
using namespace std;
const int N = 1000;
int a[N][N];
int n, m;
bool valid(int i, int j, int k, int l) {
  return k >= 0 && l >= 0 && k < n && l < m;
}
const long long INF = 1e18;
struct MCF {
  int n;
  vector<long long> prio, curflow, prevedge, prevnode, pot;
  priority_queue<long long, vector<long long>, greater<long long>> q;
  struct edge {
    int to, rev;
    long long f, cap, cost;
  };
  vector<vector<edge>> g;
  MCF(int n)
      : n(n), prio(n), curflow(n), prevedge(n), prevnode(n), pot(n), g(n) {}
  void add_edge(int s, int t, long long cap, long long cost) {
    g[s].push_back((edge){t, ((int)g[t].size()), 0, cap, cost});
    g[t].push_back((edge){s, ((int)g[s].size()) - 1, 0, 0, -cost});
  }
  pair<long long, long long> get_flow(int s, int t) {
    long long flow = 0, flowcost = 0;
    while (1) {
      q.push(s);
      fill(prio.begin(), prio.end(), INF);
      prio[s] = 0;
      curflow[s] = INF;
      while (!q.empty()) {
        long long cur = q.top();
        int d = cur >> 32, u = cur;
        q.pop();
        if (d != prio[u]) continue;
        for (int i = 0; i < ((int)g[u].size()); ++i) {
          edge &e = g[u][i];
          int v = e.to;
          if (e.cap <= e.f) continue;
          long long nprio = prio[u] + e.cost + pot[u] - pot[v];
          if (prio[v] > nprio) {
            prio[v] = nprio;
            q.push(((long long)nprio << 32) + v);
            prevnode[v] = u;
            prevedge[v] = i;
            curflow[v] = min(curflow[u], e.cap - e.f);
          }
        }
      }
      if (prio[t] == INF) break;
      for (int i = 0; i < n; i++) pot[i] += prio[i];
      long long df = min(curflow[t], INF - flow);
      flow += df;
      for (int v = t; v != s; v = prevnode[v]) {
        edge &e = g[prevnode[v]][prevedge[v]];
        e.f += df;
        g[v][e.rev].f -= df;
        flowcost += df * e.cost;
      }
    }
    return {flow, flowcost};
  }
};
vector<pair<int, int>> moves = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
int main() {
  cin >> n >> m;
  for (int i = 0; i < n; i++)
    for (int j = 0; j < m; j++) cin >> a[i][j];
  MCF mcf(n * m + 2);
  for (int i = 0; i < n; i++)
    for (int j = 0; j < m; j++) {
      if ((i + j) % 2 == 0) {
        mcf.add_edge(n * m, i * m + j, 1, 0);
        for (auto mov : moves) {
          int ni = i + mov.first, nj = j + mov.second;
          if (valid(i, j, ni, nj)) {
            mcf.add_edge(i * m + j, ni * m + nj, 1, a[i][j] != a[ni][nj]);
          }
        }
      } else
        mcf.add_edge(i * m + j, n * m + 1, 1, 0);
    }
  auto p = mcf.get_flow(n * m, n * m + 1);
  cout << p.second << endl;
  return 0;
}
