//https://ac.nowcoder.com/acm/problem/235250
//状态压缩枚举
#include <bits/stdc++.h>
using namespace std;
#define forn(i,n) for(int i=0;i<n;++i)
#define ll long long
#define inf INT_MAX
#define js ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define endl '\n'
typedef  pair<int,int> PII;
const int  N = 110,M=15;
int n,m;
int a[N][M],b[N][M];//因为不知道是翻到0或者1的step哪个更少,所以模拟两遍
vector<int> v;
int mx[5]={0,-1,1,0,0};//本身及上下左右翻转
int my[5]={0,0,0,-1,1};

bool jud(int x,int y) {//判断边界
    return x>=0&&x<n&&y>=0&&y<m;
}
void reverse(int x,int y){//模拟翻转的过程,以x,y为中心进行
    for (int i=0;i<5;++i) {
        int xx=x+mx[i],yy=y+my[i];
        if (jud(xx,yy)) a[xx][yy]=a[xx][yy]==0?1:0;
    }
}
ll solve(int i,int tar) {
    ll step=0;
    forn(j,n)
        forn(k,m)
    a[j][k]=b[j][k];
    for (int j=0;j<m;++j) {//先对第一行进行处理
        if (i&(1<<j)) {//这里是位与的知识,循环外的i是0-2的m次,这条语句在于判断
            step++;
            reverse(0,j);
        }
    }/*
    这里的reverse与下面循环的没有关系,
    上面是在尝试将第一行每个元素都翻一遍,
    我把他理解成二进制枚举对实际第一行反转结果的映射,
    这种情况显然是一一对应的
        枚举了第一行就约等于枚举整个棋盘
    */
    for (int j=0;j<n-1;++j) {
        for (int k=0;k<m;++k) {
            if (a[j][k]!=tar) {
                step++;
                reverse(j+1,k);
            }
        }
    }
    for (int j=0;j<m;++j) {
        if (a[n-1][j]!=tar)return inf;
    }
    return step;
}
int main() {
    js;cin>>n>>m;
    forn(i,n) {//这里输入格式没注意,找了一圈才发现TVT也可以用scanf控制读取
        string s;cin>>s;
        forn(j,m) {
            b[i][j]=s[j]-'0';
        }
    }
    ll ans=inf;
    for (int i=0;i<(1<<m);++i) {
        ans=min(ans,solve(i,1));
        ans=min(ans,solve(i,0));
    }
    if (ans==inf)cout<<"Impossible"<<endl;
    else cout<<ans<<endl;
    return 0;
}