//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;
}