#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int D1[] = {1, 0, -1, 0}, D2[] = {0, 1, 0, -1};
struct edge {
  int nod1, nod2, cost, cap;
  int rev;
  edge(){};
  edge(int _nod1, int _nod2, int _cost, int _cap, int _rev) {
    nod1 = _nod1;
    nod2 = _nod2;
    cost = _cost;
    cap = _cap;
    rev = _rev;
  }
};
int N, M, B;
int A[82][82];
int E1[3206], E2[3206];
vector<edge> V[6500];
int E[6500];
vector<edge>::iterator T[6500];
queue<int> Q;
bool inQ[6500];
int result;
inline int myabs(int x) { return (x < 0 ? -x : x); }
bool findPath() {
  for (int i = 0; i <= B; ++i) E[i] = INF;
  E[0] = 0;
  Q.push(0);
  inQ[0] = true;
  while (!Q.empty()) {
    int now = Q.front();
    Q.pop();
    inQ[now] = false;
    for (vector<edge>::iterator it = V[now].begin(); it != V[now].end(); ++it)
      if (it->cap && E[now] + it->cost < E[it->nod2]) {
        E[it->nod2] = E[now] + it->cost;
        T[it->nod2] = it;
        if (!inQ[it->nod2]) {
          Q.push(it->nod2);
          inQ[it->nod2] = true;
        }
      }
  }
  if (E[B] == INF) return false;
  result += E[B];
  int now = B;
  while (now != 0) {
    --T[now]->cap;
    ++V[T[now]->nod2][T[now]->rev].cap;
    now = T[now]->nod1;
  }
  return true;
}
int main() {
  cin >> N >> M;
  for (int i = 1; i <= N; ++i)
    for (int j = 1; j <= M; ++j) {
      cin >> A[i][j];
      if ((i + j) % 2 == 0)
        E1[++E1[0]] = (i - 1) * M + (j - 1);
      else
        E2[++E2[0]] = (i - 1) * M + (j - 1);
    }
  for (int i = 1; i <= E1[0]; ++i) {
    V[0].push_back(edge(0, i, 0, 1, V[i].size()));
    V[i].push_back(edge(i, 0, 0, 0, V[0].size() - 1));
  }
  for (int i = 1; i <= E2[0]; ++i) {
    V[E1[0] + i].push_back(
        edge(E1[0] + i, E1[0] + E2[0] + 1, 0, 1, V[E1[0] + E2[0] + 1].size()));
    V[E1[0] + E2[0] + 1].push_back(
        edge(E1[0] + E2[0] + 1, E1[0] + i, 0, 0, V[E1[0] + i].size() - 1));
  }
  for (int i = 1; i <= E1[0]; ++i)
    for (int j = 1; j <= E2[0]; ++j) {
      int in1 = E1[i] / M + 1, jn1 = E1[i] % M + 1;
      int in2 = E2[j] / M + 1, jn2 = E2[j] % M + 1;
      if (myabs(in1 - in2) + myabs(jn1 - jn2) == 1) {
        int cost = (A[in1][jn1] == A[in2][jn2] ? 0 : 1);
        V[i].push_back(edge(i, E1[0] + j, cost, 1, V[E1[0] + j].size()));
        V[E1[0] + j].push_back(edge(E1[0] + j, i, -cost, 0, V[i].size() - 1));
      }
    }
  B = E1[0] + E2[0] + 1;
  while (findPath())
    ;
  cout << result << '\n';
}
