#include<bits/stdc++.h>
#define rep(i, n) for(int i=0;i<(n);++i)
#define per(i, n) for(int i=(n)-1;i>=0;--i)
#define repa(i, n) for(int i=1;i<(n);++i)
#define foreach(i, n) for(auto &i:(n))
#define pii pair<int, int>
#define pll pair<long long, long long>
#define all(x) (x).begin(), (x).end()
#define bit(x) (1ll << (x))
using namespace std;
using ll = long long;
const ll MOD = (ll)1e9+7;
//const ll MOD = 998244353;
//const ll MOD = 924844033;
const int INF = (ll)1e9+7;
const ll INFLL = (ll)1e18;
const double EPS = 1e-5;
using namespace std;
template<class t>
using vvector = vector<vector<t>>;
template<class t>
using vvvector = vector<vector<vector<t>>>;
template<class t>
using priority_queuer = priority_queue<t, vector<t>, greater<t>>;
template<class t, class u> bool chmax(t &a, u b){if(a<b){a=b;return true;}return false;}
template<class t, class u> bool chmin(t &a, u b){if(a>b){a=b;return true;}return false;}

#ifdef DEBUG
#define OUTPUT(x) (output(x), outendl())
#else
#define OUTPUT(x) (void)0
#endif

ll modpow(ll x, ll b){
	ll res = 1;
	while(b){
		if(b&1)res = res * x % MOD;
		x = x * x % MOD;
		b>>=1;
	}
	return res;
}

ll modinv(ll x){
	return modpow(x, MOD-2);
}

bool was_output = false;
template<class t>
void output(t a){
	if(was_output)cout << " ";
	cout << a;
	was_output = true;
}
void outendl(){
	was_output = false;
	cout << endl;
}

int h;
int w;
vvector<char> colors;

int cul_cost(int place,int ld,int rd){
    static vvvector<int> memo(301,vvector<int>(301,vector<int>(301,-1)));
    if(memo[place][ld][rd]>=0)return memo[place][ld][rd];
    int res = 0;
    if(ld > rd){
        int dis = ld - rd;
        rep(i,h-ld){
            res += colors[place][i] == colors[place+1][i+dis];
        }
        rep(i,h-ld){
            memo[place][ld+i][rd+i] = res;
            int p = h - ld - i - 1;
            res -= colors[place][p] == colors[place+1][p+dis];
        }
    }else{
        int dis = rd - ld;
        rep(i,h-rd){
            res += colors[place][i+dis] == colors[place+1][i];
        }
        rep(i,h-rd){
            memo[place][ld+i][rd+i] = res;
            int p = h - rd - i - 1;
            res -= colors[place][p+dis] == colors[place+1][p];
        }
    }
    return memo[place][ld][rd];
}

int func2(int place,int ld,int rd){
    static vvvector<int> dp(301,vvector<int>(301,vector<int>(301,-1)));
    if(dp[place][ld][rd]>=0)return dp[place][ld][rd];
    int res = INF;
    if(ld<h){
        chmin(res,cul_cost(place,ld,rd) + func2(place,ld+1,rd));
    }
    if(rd<h){
        chmin(res,cul_cost(place,ld,rd) + func2(place,ld,rd+1));
    }
    if(ld==h||rd==h){
        return 0;
    }
    return dp[place][ld][rd] = res;
}
int func(int l,int r){
    static vvector<int> dp(301,vector<int>(301,-1));
    if(dp[l][r]>=0)return dp[l][r];
    if(r==l)return 0;
    if(r-l==1){
        return func2(l,0,0);
    }
    int res = INF;
    for(int mid=l;mid<r;++mid){
        chmin(res,func(l,mid)+func(mid+1,r)+func(mid,mid+1));
    }
    return dp[l][r] = res;
}

int main(){
    cin >> h >> w;
    colors.resize(w);
    rep(y,h){
        rep(x,w){
            char d;
            cin >> d;
            colors[x].push_back(d);
        }
    }
    rep(i,w-1){
        rep(j,h){
            cul_cost(i,0,j);
            cul_cost(i,j,0);
        }
    }
    cout << func(0,w-1) << endl;
    return 0;
}


Measured memory_bytes: 222720