#include <bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:16000000")
const int INF = 1e9;
const double EPS = 1e-8;
const double PI = 2 * acos(0.);
struct edge {
  int v, c, f, rev, cost;
  edge(int vv, int cc, int ff, int revrev, int costcost) {
    v = vv;
    c = cc;
    f = ff;
    rev = revrev;
    cost = costcost;
  }
};
vector<edge> v[10000];
void add_edge(int u1, int u2, int c, int cost) {
  v[u1].push_back(edge(u2, c, c, v[u2].size(), cost));
  v[u2].push_back(edge(u1, 0, 0, v[u1].size() - 1, -cost));
}
int d[2][4] = {0, 0, 1, -1, 1, -1, 0, 0};
int dist[10000];
bool color[10000];
pair<int, int> par[10000];
const int T = 1 << 17;
int Q[T];
int n;
int fb(int s, int t) {
  memset(dist, 0x3f, sizeof(dist));
  memset(color, 0, sizeof(color));
  dist[s] = 0;
  par[s] = make_pair(-1, -1);
  int l = 0;
  int r = 1;
  Q[0] = s;
  while (l != r) {
    int u = Q[l];
    color[u] = false;
    l = (l + 1) & (T - 1);
    for (int j = 0; j < v[u].size(); ++j) {
      if (dist[v[u][j].v] > dist[u] + v[u][j].cost && v[u][j].f > 0) {
        dist[v[u][j].v] = dist[u] + v[u][j].cost;
        par[v[u][j].v] = make_pair(u, j);
        if (!color[v[u][j].v]) {
          Q[r] = v[u][j].v;
          r = (r + 1) & (T - 1);
          color[v[u][j].v] = true;
        }
      }
    }
  }
  int cur = t;
  while (cur > 0) {
    int i = par[cur].first;
    int j = par[cur].second;
    v[i][j].f -= 1;
    v[v[i][j].v][v[i][j].rev].f += 1;
    cur = i;
  }
  return dist[t];
}
int a[100][100];
int num[100][100];
int main() {
  int n, m;
  scanf("%d%d", &n, &m);
  int k = 2;
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < m; ++j) {
      scanf("%d", &a[i][j]);
      num[i][j] = k++;
    }
  }
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < m; ++j) {
      if ((i + j) % 2 == 0) {
        add_edge(0, num[i][j], 1, 0);
      } else {
        add_edge(num[i][j], 1, 1, 0);
      }
      for (int dir = 0; dir < 4; ++dir) {
        int x = i + d[0][dir];
        int y = j + d[1][dir];
        if (x < 0 || x >= n || y < 0 || y >= m) continue;
        if ((i + j) % 2 == 0)
          add_edge(num[i][j], num[x][y], 1, a[i][j] == a[x][y] ? -1 : 0);
        else
          add_edge(num[x][y], num[i][j], 1, a[i][j] == a[x][y] ? -1 : 0);
      }
    }
  }
  int ans = 0;
  for (int i = 0; i < n * m / 2; ++i) ans += fb(0, 1);
  printf("%d\n", (n * m / 2 + ans));
  return 0;
}
