Problem:
Score : 1000 points

Problem Statement

Note the unusual memory limit.

For a rectangular grid where each square is painted white or black, we define its complexity as follows:

If all the squares are black or all the squares are white, the complexity is 0.

Otherwise, divide the grid into two subgrids by a line parallel to one of the sides of the grid, and let c_1 and c_2 be the complexities of the subgrids. There can be multiple ways to perform the division, and let m be the minimum value of \max(c_1, c_2) in those divisions. The complexity of the grid is m+1.

You are given a grid with H horizontal rows and W vertical columns where each square is painted white or black.
HW characters from A_{11} to A_{HW} represent the colors of the squares.
A_{ij} is # if the square at the i-th row from the top and the j-th column from the left is black, and A_{ij} is . if that square is white.

Find the complexity of the given grid.

Constraints

1 \leq H,W \leq 185

A_{ij} is # or ..

Input

Input is given from Standard Input in the following format:

H W
A_{11}A_{12}...A_{1W}
:
A_{H1}A_{H2}...A_{HW}

Output

Print the complexity of the given grid.

Sample Input 1

3 3
...
.##
.##

Sample Output 1

2

Let us divide the grid by the boundary line between the first and second columns.
The subgrid consisting of the first column has the complexity of 0, and the subgrid consisting of the second and third columns has the complexity of 1, so the whole grid has the complexity of at most 2.

Sample Input 2

6 7
.####.#
#....#.
#....#.
#....#.
.####.#
#....##

Sample Output 2

4

Solution in C++14 (GCC 5.4.1) (judge verdict: Time Limit Exceeded)

//Zory-2019
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
// typedef __int128 ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
#define FR first
#define SE second
#define MP make_pair
#define PB push_back
#define vc vector
#define all(x) (x).begin(),(x).end()
#define sz(x) ((int)(x).size())
#define bin(x) (1ll<<(x))
#define fo(i,l,r) for(int i=(l),I=(r);i<=I;i++)
#define fd(i,r,l) for(int i=(r),I=(l);i>=I;i--)
#define Debug printf("Passing [%s] in LINE %d\n",__FUNCTION__,__LINE__)
#define debug(x) cerr<<#x<<'='<<x<<endl
#define mem(x,val) memset(x,val,sizeof x)
namespace mine
{
    ll qread()
    {
        ll ans=0,f=1;char c=getchar();
        while(c<'0' or c>'9') {if(c=='-')f=-1;c=getchar();}
        while('0'<=c and c<='9') ans=ans*10+c-'0',c=getchar();
        return ans*f;
    }
    void write(ll num){if(num<0) putchar('-'),num=-num;if(num>=10) write(num/10);putchar('0'+num%10);}
    void write1(ll num){write(num);putchar(' ');}
    void write2(ll num){write(num);putchar('\n');}
    template<typename T> void chmax(T &x,const T y) {x=(x>y?x:y);}
    template<typename T> void chmin(T &x,const T y) {x=(x<y?x:y);}
    ll gcd(ll x,ll y){return y?gcd(y,x%y):x;}
    bool IN(ll x,ll l,ll r){return l<=x and x<=r;}

    const int INF=0x3f3f3f3f;
    const int MOD=1e9;
    int mm(const int x){return x>=MOD?x-MOD:x;}
    template<typename T> void add(T &x,const int &y){x=(x+y>=MOD?x+y-MOD:x+y);}
    ll qpower(ll x,ll e,int mod=MOD){ll ans=1;while(e){if(e&1)ans=ans*x%mod;x=x*x%mod;e>>=1;}return ans;}
    ll invm(ll x){return qpower(x,MOD-2);}
    const int N=200+10;

    int cnt[N][N];char str[N];
    inline bool same(int x1,int x2,int y1,int y2){
        int tmp=cnt[x2][y2]-cnt[x1-1][y2]-cnt[x2][y1-1]+cnt[x1-1][y1-1];
        return tmp==(x2-x1+1)*(y2-y1+1) or !tmp;
    }
    map<short,short> done[N][N][N];
    int solve(short x1,short x2,short y1,short y2)
    {
        if(same(x1,x2,y1,y2)) return 0;
        if(done[x1][x2][y1].count(y2)) return done[x1][x2][y1][y2];
        int ret=INF;
        {
            int fl=x1,fr=x2-1,pos=x1-1;
            while(fl<=fr)
            {
                int mid=(fl+fr)/2;
                if(solve(x1,mid,y1,y2)<=solve(mid+1,x2,y1,y2)) pos=mid,fl=mid+1; else fr=mid-1;
            }
            if(pos>=x1) chmin(ret,solve(pos+1,x2,y1,y2));
            if(pos+1<x2) chmin(ret,solve(x1,pos+1,y1,y2));
            // fo(i,x1,x2-1) chmin(ret,max(solve(x1,i,y1,y2),solve(i+1,x2,y1,y2))+1);
        }
        {
            int fl=y1,fr=y2-1,pos=y1-1;
            while(fl<=fr)
            {
                int mid=(fl+fr)/2;
                if(solve(x1,x2,y1,mid)<=solve(x1,x2,mid+1,y2)) pos=mid,fl=mid+1; else fr=mid-1;
            }
            if(pos>=y1) chmin(ret,solve(x1,x2,pos+1,y2));
            if(pos+1<y2) chmin(ret,solve(x1,x2,y1,pos+1));
            // fo(i,y1,y2-1) chmin(ret,max(solve(x1,x2,y1,i),solve(x1,x2,i+1,y2))+1);
        }
        // printf("f[%d][%d][%d][%d]=%d\n",x1,x2,y1,y2,ret);
        return done[x1][x2][y1][y2]=ret+1;
    }
    void main()
	{
        int n=qread(),m=qread();
        fo(i,1,n){scanf("%s",str+1);fo(j,1,m) cnt[i][j]=cnt[i][j-1]+(str[j]=='#');}
        fo(j,1,m) fo(i,1,n) cnt[i][j]+=cnt[i-1][j];
        write(solve(1,n,1,m));
	}
};//(ans+MOD)%MOD
signed main()
{
    srand(time(0));
    mine::main();
}