#include <bits/stdc++.h>
using namespace std;
const double PI = acos(-1.0);
const int INF = 1000 * 1000 * 1000 + 7;
const long long LINF = INF * (long long)INF;
const int MAX = 10 * 1000;
const int MAXN = 100;
const int DX[4] = {1, 0, -1, 0}, DY[4] = {0, 1, 0, -1};
struct edge {
  int to, cap, flow, cost;
  edge(int to, int cap, int flow, int cost)
      : to(to), cap(cap), flow(flow), cost(cost) {}
};
vector<int> g[MAX];
vector<edge> E;
int N;
int D[MAX];
int Par[MAX];
int T[MAX];
deque<int> Q;
void addEdge(int u, int v, int cap, int cost) {
  g[u].push_back((int)((E).size()));
  E.push_back(edge(v, cap, 0, cost));
  g[v].push_back((int)((E).size()));
  E.push_back(edge(u, 0, 0, -cost));
}
pair<int, int> Flow(int s, int t) {
  int flow = 0, price = 0;
  while (true) {
    for (int i = (0); i < (N); ++i) {
      D[i] = INF;
      T[i] = 0;
    }
    D[s] = 0;
    Q.push_back(s);
    T[s] = 1;
    while (!Q.empty()) {
      int v = Q.front();
      Q.pop_front();
      for (int i = (0); i < ((int)((g[v]).size())); ++i) {
        int id = g[v][i], to = E[id].to;
        if (E[id].flow == E[id].cap) continue;
        if (D[to] > D[v] + E[id].cost) {
          D[to] = D[v] + E[id].cost;
          Par[to] = id;
          if (T[to] == 0) {
            Q.push_back(to);
            T[to] = 1;
          }
          if (T[to] == 2) {
            Q.push_front(to);
            T[to] = 1;
          }
        }
      }
      T[v] = 2;
    }
    if (D[t] == INF) return make_pair(flow, price);
    int pushed = INF;
    int v = t;
    while (v != s) {
      int id = Par[v];
      pushed = min(pushed, E[id].cap - E[id].flow);
      v = E[id ^ 1].to;
    }
    v = t;
    while (v != s) {
      int id = Par[v];
      E[id].flow += pushed;
      E[id ^ 1].flow -= pushed;
      v = E[id ^ 1].to;
    }
    flow += pushed;
    price += pushed * D[t];
  }
}
int n, m;
int A[MAXN][MAXN];
int getVertex(int r, int c) { return m * r + c; }
int main() {
  ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
  cin >> n >> m;
  for (int i = (0); i < (n); ++i)
    for (int j = (0); j < (m); ++j) cin >> A[i][j];
  int s = n * m, t = s + 1;
  N = s + 2;
  for (int i = (0); i < (n); ++i)
    for (int j = (0); j < (m); ++j)
      if ((i ^ j) & 1) {
        addEdge(s, getVertex(i, j), 1, 0);
        for (int k = (0); k < (4); ++k)
          if (i + DX[k] >= 0 && i + DX[k] < n && j + DY[k] >= 0 &&
              j + DY[k] < m)
            addEdge(getVertex(i, j), getVertex(i + DX[k], j + DY[k]), 1,
                    A[i][j] != A[i + DX[k]][j + DY[k]]);
      } else
        addEdge(getVertex(i, j), t, 1, 0);
  cout << Flow(s, t).second;
  return 0;
}
