#include <iostream>
#include <fstream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <string>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <deque>
#include <bitset>
#include <algorithm>
#include <complex>
#include <array>
using namespace std;
 
#define REP(i,n) for(int i=0; i<n; ++i)
#define FOR(i,a,b) for(int i=a; i<=b; ++i)
#define FORR(i,a,b) for (int i=a; i>=b; --i)
#define ALL(c) (c).begin(), (c).end()
 
typedef long long ll;
typedef vector<int> VI;
typedef vector<ll> VL;
typedef vector<VI> VVI;
typedef vector<VL> VVL;
typedef pair<int,int> P;
typedef pair<ll,ll> PL;
typedef vector<double> VD;
typedef vector<VD> VVD;

template<typename T> void chmin(T &a, T b) { if (a > b) a = b; }
// template<typename T> void chmax(T &a, T b) { if (a < b) a = b; }
void chmax(unsigned char &a, int b) { if (a < b) a = b; }

int in() { int x; scanf("%d", &x); return x; }
ll lin() { ll x; scanf("%lld", &x); return x; }

const int N = 186, M = 17;
unsigned char dph[M][N][N][N], dpw[M][N][N][N];

template<typename T>
struct cumsum2D{
    int n, m;
    vector<vector<T>> dat;

    cumsum2D(){}
    cumsum2D(vector<vector<T>> &x){
        n = x.size();
        m = x[0].size();
        dat.assign(n+1, vector<T>(m+1));
        for (int i = 0; i < n; i++) for (int j = 0; j < m; j++){
            dat[i+1][j+1] = dat[i+1][j] + dat[i][j+1] - dat[i][j] + x[i][j];
        }
    }

    // [0, x) * [0, y)
    T sum(int x, int y){
        return dat[x][y];
    }

    // [x0, x1) * [y0 * y1)
    T sum(int x0, int y0, int x1, int y1){
        return sum(x1, y1) - sum(x0, y1) - sum(x1, y0) + sum(x0, y0);
    }
};

int main() {
    int h, w;
    cin >> h >> w;
    vector<string> s(h);
    REP(i,h) cin >> s[i];

    VVI c(h, VI(w));
    REP(i,h) REP(j,w) c[i][j] = (s[i][j] == '#');
    cumsum2D<int> cumsum(c);

    REP(i1,h) REP(j1,w) FOR(i2,i1+1,h) FOR(j2,j1+1,w){
        int s = cumsum.sum(i1, j1, i2, j2);
        if (s == 0 || s == (i2 - i1) * (j2 - j1)){
            chmax(dph[0][i1][j1][j2], i2 - i1);
            chmax(dpw[0][i1][j1][i2], j2 - j1);
        }
    }

    REP(t,M-1){
        REP(i1,h) REP(j1,w){
            FOR(j2,j1+1,w){
                int x = dph[t][i1][j1][j2];
                chmax(dph[t+1][i1][j1][j2], x + dph[t][i1 + x][j1][j2]);
                chmax(dpw[t+1][i1][j1][i1 + dph[t+1][i1][j1][j2]], j2 - j1);
            }
            FOR(i2,i1+1,h){
                int x = dpw[t][i1][j1][i2];
                chmax(dpw[t+1][i1][j1][i2], x + dpw[t][i1][j1 + x][i2]);
                chmax(dph[t+1][i1][j1][j1 + dpw[t+1][i1][j1][i2]], i2 - i1);
            }
        }
        REP(i1,h){
            FORR(len,w,1){
                REP(j1,w-len+1){
                    int j2 = j1 + len;
                    if (j1 > 0) chmax(dph[t+1][i1][j1][j2], dph[t+1][i1][j1-1][j2]);
                    if (j2 < w) chmax(dph[t+1][i1][j1][j2], dph[t+1][i1][j1][j2+1]);
                }
            }
        }
        REP(j1,w){
            FORR(len,h,1){
                REP(i1,h-len+1){
                    int i2 = i1 + len;
                    if (i1 > 0) chmax(dpw[t+1][i1][j1][i2], dpw[t+1][i1-1][j1][i2]);
                    if (i2 < h) chmax(dpw[t+1][i1][j1][i2], dpw[t+1][i1][j1][i2+1]);
                }
            }
        }
    }

    REP(t,M){
        if (dph[t][0][0][w] == h){
            cout << t << endl;
            return 0;
        }
    }

    return 0;
}


Measured memory_bytes: 214272