/*
 * Author    : raj1307 - Raj Singh
 * Date      : 10.10.2020
 */

#pragma GCC optimize("Ofast")
// #pragma GCC optimize("unroll-loops")
// #define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;

#define fio ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define fr(i, a, b) for(int i = (a); i < (b); ++i)
#define fb(i, b, a) for(int i = (b); i > (a); --i)
#define fill(x,y) memset(x,y,sizeof(x))
#define rr return
#define mp make_pair
#define pb push_back
#define sz(x) ((int)x.size())
#define int long long
//#define ll long long
#define ld long double
#define S second
#define F first
#define endl "\n"
#define Endl "\n"
#define all(v) (v).begin(), (v).end()
typedef pair<int, int> pii;
int max(int a,int b){if(a>b) return a; else return b;}
int min(int a,int b){if(a>b) return b; else return a;}
int gcd(int a,int b){ return (b == 0) ? a : gcd(b, a % b);}
inline int lcm(int a,int b){ return a / gcd(a, b) * b;}
inline int normalize(int x,int mod){ x %= mod; if (x < 0) x += mod; return x;}

int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
string abc="abcdefghijklmnopqrstuvwxyz";
const double PI=acosl(-1);
const int mod = 1000*1000*1000+7;
//const int mod = 998244353;
const int inf = 1e18 +5;

//a and b are assumed to be taken modulo p
inline int add(int a, int b, int p = mod){ int c = a + b; if(c >= p) c -= p; return c; }
inline int sub(int a, int b, int p = mod){ int c = a - b; if(c < 0) c += p; return c; }
inline int mul(int a, int b, int p = mod){ return (a * 1ll * b) % p; }

// template<typename T>
// using ordered_set = tree<T,null_type,less<T>,rb_tree_tag,tree_order_statistics_node_update>;
//1. order_of_key(k) : number of elements strictly lesser than k
//2. find_by_order(k) : k-th element in the set
//To make it an ordered_multiset, use pairs of (value, time_of_insertion)
//to distinguish values which are similar.

int floor1(int n,int k){
    if(n%k == 0 || n >= 0)return n/k;
    return (n/k)-1;
}

int ceil1(int n,int k){
    return floor1(n+k-1,k);
}

int powm(int a, int b) {
    int res=1;
    while(b) {
        if(b&1)
            res=(res*a)%mod;
        a=(a*a)%mod;
        b>>=1;
    }
    return res;
}

const int N = 1e6 + 5;

int n,m;
string s[N];
string t[N];

int cache[N][(1<<3) +5]; // changes

int dp(int pos,int last){

    if(pos==n)
        return 0;

    int &ans=cache[pos][last];
    if(ans!=-1)
        return ans;

    ans=inf;

    fr(cur,0,1<<m){

        fr(i,0,m){

            if(i+1<m){

                int x1=((1<<i)&last!=0);
                int x2=((1<<(i+1))&last!=0);
                int x3=((1<<i)&cur!=0);
                int x4=((1<<(i+1))&cur!=0);
                int cnt=x1+x2+x3+x4;

                //cout<<pos<<" "<<last<<" "<<cur<<" "<<cnt<<endl;

                if(cnt%2){

                    int changes= (x1!=(s[pos][i]-'0')) + (x1!=(s[pos][i+1]-'0'));
                    ans=min(ans,changes+dp(pos+1,cur));
                }

            }

        }

    }

    return ans;

}

void solve(){

    cin>>n>>m;
    fr(i,0,n){
        cin>>s[i];
    }

    //fill(cache,-1);
    // fr(i,0,n){
    //     fr(j,0,1<<m)
    //         cache[i][j]=-1;
    // }

    if(min(n,m)>3){
        cout<<-1;
        return;
    }

    if(n<m){

        fr(i,0,m){
            fr(j,0,n){
                t[i]+=s[j][i];
            }
        }
        fr(i,0,m){
            s[i]=t[i];
        }
        n=n+m-(m=n);
        cout<<n<<" "<<m<<endl;

    }

    int mn=n*m;

    if(m==4)
        cout<<-1;

    fr(i,0,1<<m){
        int ch=0;
        fr(j,0,m){
            if((1<<j)&i){
                if(s[0][j]=='0')
                    ++ch;
            }else{
                if(s[0][j]=='1')
                    ++ch;
            }

        }

        //cout<<ch<<" "<<i<<endl;

        //mn=min(mn,ch+dp(1,i));
    }

    cout<<mn;

}

signed main() {
    fio;
    #ifndef ONLINE_JUDGE
        freopen("input.txt", "r", stdin);
        freopen("output.txt", "w", stdout);
        //freopen("error.txt", "w", stderr);
    #endif
    cout<<fixed<<setprecision(10);
    int t=1;
    //cin>>t;  // UNCOMMENT FOR TEST-CASES
    //precompute();
    int cnt=1;
    while(t--) {
        //cout<<"Case #"<<cnt++<<": ";
        solve();
    }
    return 0;
}


/*
 * Author    : raj1307 - Raj Singh
 * Date      : 10.10.2020
 */

#pragma GCC optimize("Ofast")
// #pragma GCC optimize("unroll-loops")
// #define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;

#define fio ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define fr(i, a, b) for(int i = (a); i < (b); ++i)
#define fb(i, b, a) for(int i = (b); i > (a); --i)
#define fill(x,y) memset(x,y,sizeof(x))
#define rr return
#define mp make_pair
#define pb push_back
#define sz(x) ((int)x.size())
#define int long long
//#define ll long long
#define ld long double
#define S second
#define F first
#define endl "\n"
#define Endl "\n"
#define all(v) (v).begin(), (v).end()
typedef pair<int, int> pii;
int max(int a,int b){if(a>b) return a; else return b;}
int min(int a,int b){if(a>b) return b; else return a;}
int gcd(int a,int b){ return (b == 0) ? a : gcd(b, a % b);}
inline int lcm(int a,int b){ return a / gcd(a, b) * b;}
inline int normalize(int x,int mod){ x %= mod; if (x < 0) x += mod; return x;}

int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
string abc="abcdefghijklmnopqrstuvwxyz";
const double PI=acosl(-1);
const int mod = 1000*1000*1000+7;
//const int mod = 998244353;
const int inf = 1e18 +5;

//a and b are assumed to be taken modulo p
inline int add(int a, int b, int p = mod){ int c = a + b; if(c >= p) c -= p; return c; }
inline int sub(int a, int b, int p = mod){ int c = a - b; if(c < 0) c += p; return c; }
inline int mul(int a, int b, int p = mod){ return (a * 1ll * b) % p; }

// template<typename T>
// using ordered_set = tree<T,null_type,less<T>,rb_tree_tag,tree_order_statistics_node_update>;
//1. order_of_key(k) : number of elements strictly lesser than k
//2. find_by_order(k) : k-th element in the set
//To make it an ordered_multiset, use pairs of (value, time_of_insertion)
//to distinguish values which are similar.

int floor1(int n,int k){
    if(n%k == 0 || n >= 0)return n/k;
    return (n/k)-1;
}

int ceil1(int n,int k){
    return floor1(n+k-1,k);
}

int powm(int a, int b) {
    int res=1;
    while(b) {
        if(b&1)
            res=(res*a)%mod;
        a=(a*a)%mod;
        b>>=1;
    }
    return res;
}

const int N = 1e6 + 5;

int n,m;
string s[N];
string t[N];

int cache[N][(1<<3) +5]; // changes

int dp(int pos,int last){

    if(pos==n)
        return 0;

    int &ans=cache[pos][last];
    if(ans!=-1)
        return ans;

    ans=inf;

    fr(cur,0,1<<m){

        fr(i,0,m){

            if(i+1<m){

                int cnt=0;

                if(((1<<i)&last)!=0) ++cnt;
                if(((1<<(i+1))&last)!=0)++cnt;
                if(((1<<i)&cur)!=0) ++cnt;
                if(((1<<(i+1))&cur)!=0) ++cnt;

                int x1=(((1<<i)&last)!=0);
                int x2=(((1<<(i+1))&last)!=0);
                int x3=(((1<<i)&cur)!=0);
                int x4=(((1<<(i+1))&cur)!=0);
                //int cnt=x1+x2+x3+x4;

                if(cnt%2){

                    int changes= 0;

                    if(x3!=(s[pos][i]-'0'))
                        ++changes;
                    if(x4!=(s[pos][i+1]-'0'));
                        ++changes;

                    ans=min(ans,changes+dp(pos+1,cur));
                }

            }

        }

    }

    return ans;

}

void solve(){

    cin>>n>>m;
    fr(i,0,n){
        cin>>s[i];
    }

    //fill(cache,-1);
    fr(i,0,n){
        fr(j,0,1<<m)
            cache[i][j]=-1;
    }

    if(min(n,m)>3){
        cout<<-1;
        return;
    }

    if(n<m){

        fr(i,0,m){
            t[i]="";
            fr(j,0,n){
                t[i]+=s[j][i];
            }
        }
        fr(i,0,m){
            s[i]=t[i];
        }
        n=n+m-(m=n);

    }

    int mn=n*m;

    fr(i,0,1<<m){
        int ch=0;
        fr(j,0,m){
            if((1<<j)&i){
                if(s[0][j]=='0')
                    ++ch;
            }else{
                if(s[0][j]=='1')
                    ++ch;
            }

        }

        //cout<<ch<<" "<<i<<endl;

        mn=min(mn,ch+dp(1,i));
        //cout<<mn<<endl;
    }

    cout<<mn;

}

signed main() {
    fio;
    #ifndef ONLINE_JUDGE
        freopen("input.txt", "r", stdin);
        freopen("output.txt", "w", stdout);
        //freopen("error.txt", "w", stderr);
    #endif
    cout<<fixed<<setprecision(10);
    int t=1;
    //cin>>t;  // UNCOMMENT FOR TEST-CASES
    //precompute();
    int cnt=1;
    while(t--) {
        //cout<<"Case #"<<cnt++<<": ";
        solve();
    }
    return 0;
}


/*
 * Author    : raj1307 - Raj Singh
 * Date      : 10.10.2020
 */

#pragma GCC optimize("Ofast")
// #pragma GCC optimize("unroll-loops")
// #define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;

#define fio ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define fr(i, a, b) for(int i = (a); i < (b); ++i)
#define fb(i, b, a) for(int i = (b); i > (a); --i)
#define fill(x,y) memset(x,y,sizeof(x))
#define rr return
#define mp make_pair
#define pb push_back
#define sz(x) ((int)x.size())
#define int long long
//#define ll long long
#define ld long double
#define S second
#define F first
#define endl "\n"
#define Endl "\n"
#define all(v) (v).begin(), (v).end()
typedef pair<int, int> pii;
int max(int a,int b){if(a>b) return a; else return b;}
int min(int a,int b){if(a>b) return b; else return a;}
int gcd(int a,int b){ return (b == 0) ? a : gcd(b, a % b);}
inline int lcm(int a,int b){ return a / gcd(a, b) * b;}
inline int normalize(int x,int mod){ x %= mod; if (x < 0) x += mod; return x;}

int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
string abc="abcdefghijklmnopqrstuvwxyz";
const double PI=acosl(-1);
const int mod = 1000*1000*1000+7;
//const int mod = 998244353;
const int inf = 1e18 +5;

//a and b are assumed to be taken modulo p
inline int add(int a, int b, int p = mod){ int c = a + b; if(c >= p) c -= p; return c; }
inline int sub(int a, int b, int p = mod){ int c = a - b; if(c < 0) c += p; return c; }
inline int mul(int a, int b, int p = mod){ return (a * 1ll * b) % p; }

// template<typename T>
// using ordered_set = tree<T,null_type,less<T>,rb_tree_tag,tree_order_statistics_node_update>;
//1. order_of_key(k) : number of elements strictly lesser than k
//2. find_by_order(k) : k-th element in the set
//To make it an ordered_multiset, use pairs of (value, time_of_insertion)
//to distinguish values which are similar.

int floor1(int n,int k){
    if(n%k == 0 || n >= 0)return n/k;
    return (n/k)-1;
}

int ceil1(int n,int k){
    return floor1(n+k-1,k);
}

int powm(int a, int b) {
    int res=1;
    while(b) {
        if(b&1)
            res=(res*a)%mod;
        a=(a*a)%mod;
        b>>=1;
    }
    return res;
}

const int N = 1e6 + 5;

int n,m;
string s[N];
string t[N];

int cache[N][(1<<3) +5]; // changes

int dp(int pos,int last){

    if(pos==n)
        return 0;

    int &ans=cache[pos][last];
    if(ans!=-1)
        return ans;

    ans=inf;

    fr(cur,0,1<<m){

        int flag=1;

        fr(i,0,m){

            if(i+1<m){

                int cnt=0;

                if(((1<<i)&last)!=0) ++cnt;
                if(((1<<(i+1))&last)!=0)++cnt;
                if(((1<<i)&cur)!=0) ++cnt;
                if(((1<<(i+1))&cur)!=0) ++cnt;

                if(cnt%2==0){
                    flag=0;
                    break;
                }
            }

        }

        if(flag){

            int changes= 0;

            fr(i,0,m){
                if((1<<i)&cur){
                    if(s[pos][i]=='0')
                        ++changes;
                    }else{
                        if(s[pos][i]=='1')
                            ++changes;
                    }
            }

            ans=min(ans,changes+dp(pos+1,cur));
        }

    }

    return ans;

}

void solve(){

    cin>>n>>m;
    fr(i,0,n){
        cin>>s[i];
    }

    if(min(n,m)==1){
        cout<<0;
        return;
    }

    //fill(cache,-1);

    if(min(n,m)>3){
        cout<<-1;
        return;
    }

    if(n<m){

        fr(i,0,m){
            t[i]="";
            fr(j,0,n){
                t[i]+=s[j][i];
            }
        }
        fr(i,0,m){
            s[i]=t[i];
        }
        n=n+m-(m=n);
        // fr(i,0,n) cout<<s[i]<<endl;
        // cout<<n<<" "<<m<<endl;

    }

    fr(i,0,n){
        fr(j,0,1<<m)
            cache[i][j]=-1;
    }

    int mn=n*m;

    fr(i,0,1<<m){
        int ch=0;
        fr(j,0,m){
            if((1<<j)&i){
                if(s[0][j]=='0')
                    ++ch;
            }else{
                if(s[0][j]=='1')
                    ++ch;
            }

        }

        //cout<<ch<<" "<<i<<endl;

        mn=min(mn,ch+dp(1,i));
        //cout<<mn<<endl;
    }

    cout<<mn;

}

signed main() {
    fio;
    #ifndef ONLINE_JUDGE
        freopen("input.txt", "r", stdin);
        freopen("output.txt", "w", stdout);
        //freopen("error.txt", "w", stderr);
    #endif
    cout<<fixed<<setprecision(10);
    int t=1;
    //cin>>t;  // UNCOMMENT FOR TEST-CASES
    //precompute();
    int cnt=1;
    while(t--) {
        //cout<<"Case #"<<cnt++<<": ";
        solve();
    }
    return 0;
}


/*
 * Author    : raj1307 - Raj Singh
 * Date      : 10.10.2020
 */

#pragma GCC optimize("Ofast")
// #pragma GCC optimize("unroll-loops")
// #define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;

#define fio ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define fr(i, a, b) for(int i = (a); i < (b); ++i)
#define fb(i, b, a) for(int i = (b); i > (a); --i)
#define fill(x,y) memset(x,y,sizeof(x))
#define rr return
#define mp make_pair
#define pb push_back
#define sz(x) ((int)x.size())
#define int long long
//#define ll long long
#define ld long double
#define S second
#define F first
#define endl "\n"
#define Endl "\n"
#define all(v) (v).begin(), (v).end()
typedef pair<int, int> pii;
int max(int a,int b){if(a>b) return a; else return b;}
int min(int a,int b){if(a>b) return b; else return a;}
int gcd(int a,int b){ return (b == 0) ? a : gcd(b, a % b);}
inline int lcm(int a,int b){ return a / gcd(a, b) * b;}
inline int normalize(int x,int mod){ x %= mod; if (x < 0) x += mod; return x;}

int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
string abc="abcdefghijklmnopqrstuvwxyz";
const double PI=acosl(-1);
const int mod = 1000*1000*1000+7;
//const int mod = 998244353;
const int inf = 1e18 +5;

//a and b are assumed to be taken modulo p
inline int add(int a, int b, int p = mod){ int c = a + b; if(c >= p) c -= p; return c; }
inline int sub(int a, int b, int p = mod){ int c = a - b; if(c < 0) c += p; return c; }
inline int mul(int a, int b, int p = mod){ return (a * 1ll * b) % p; }

// template<typename T>
// using ordered_set = tree<T,null_type,less<T>,rb_tree_tag,tree_order_statistics_node_update>;
//1. order_of_key(k) : number of elements strictly lesser than k
//2. find_by_order(k) : k-th element in the set
//To make it an ordered_multiset, use pairs of (value, time_of_insertion)
//to distinguish values which are similar.

int floor1(int n,int k){
    if(n%k == 0 || n >= 0)return n/k;
    return (n/k)-1;
}

int ceil1(int n,int k){
    return floor1(n+k-1,k);
}

int powm(int a, int b) {
    int res=1;
    while(b) {
        if(b&1)
            res=(res*a)%mod;
        a=(a*a)%mod;
        b>>=1;
    }
    return res;
}

const int N = 1e6 + 5;

int n,m;
string s[N];
string t[N];

int cache[N][(1<<3) +5]; // changes

int dp(int pos,int last){

    if(pos==n)
        return 0;

    int &ans=cache[pos][last];
    if(ans!=-1)
        return ans;

    ans=inf;

    fr(cur,0,1<<m){

        fr(i,0,m){

            if(i+1<m){

                int x1=((1<<i)&last!=0);
                int x2=((1<<(i+1))&last!=0);
                int x3=((1<<i)&cur!=0);
                int x4=((1<<(i+1))&cur!=0);
                int cnt=x1+x2+x3+x4;

                //cout<<pos<<" "<<last<<" "<<cur<<" "<<cnt<<endl;

                if(cnt%2){

                    int changes= 0;

                    if(x3!=(s[pos][i]-'0'))
                        ++changes;
                    if(x4!=(s[pos][i+1]-'0'));
                        ++changes;

                    ans=min(ans,changes+dp(pos+1,cur));
                }

            }

        }

    }

    return ans;

}

void solve(){

    cin>>n>>m;
    fr(i,0,n){
        cin>>s[i];
    }

    //fill(cache,-1);
    fr(i,0,n){
        fr(j,0,1<<m)
            cache[i][j]=-1;
    }

    if(min(n,m)>3){
        cout<<-1;
        return;
    }

    if(n<m){

        fr(i,0,m){
            t[i]="";
            fr(j,0,n){
                t[i]+=s[j][i];
            }
        }
        fr(i,0,m){
            s[i]=t[i];
        }
        n=n+m-(m=n);

    }

    int mn=n*m;

    if(m==4)
        cout<<-1;

    fr(i,0,1<<m){
        int ch=0;
        fr(j,0,m){
            if((1<<j)&i){
                if(s[0][j]=='0')
                    ++ch;
            }else{
                if(s[0][j]=='1')
                    ++ch;
            }

        }

        //cout<<ch<<" "<<i<<endl;

        mn=min(mn,ch+dp(1,i));
        //cout<<mn<<endl;
    }

    cout<<mn;

}

signed main() {
    fio;
    #ifndef ONLINE_JUDGE
        freopen("input.txt", "r", stdin);
        freopen("output.txt", "w", stdout);
        //freopen("error.txt", "w", stderr);
    #endif
    cout<<fixed<<setprecision(10);
    int t=1;
    //cin>>t;  // UNCOMMENT FOR TEST-CASES
    //precompute();
    int cnt=1;
    while(t--) {
        //cout<<"Case #"<<cnt++<<": ";
        solve();
    }
    return 0;
}


/*
 * Author    : raj1307 - Raj Singh
 * Date      : 10.10.2020
 */

#pragma GCC optimize("Ofast")
// #pragma GCC optimize("unroll-loops")
// #define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;

#define fio ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define fr(i, a, b) for(int i = (a); i < (b); ++i)
#define fb(i, b, a) for(int i = (b); i > (a); --i)
#define fill(x,y) memset(x,y,sizeof(x))
#define rr return
#define mp make_pair
#define pb push_back
#define sz(x) ((int)x.size())
#define int long long
//#define ll long long
#define ld long double
#define S second
#define F first
#define endl "\n"
#define Endl "\n"
#define all(v) (v).begin(), (v).end()
typedef pair<int, int> pii;
int max(int a,int b){if(a>b) return a; else return b;}
int min(int a,int b){if(a>b) return b; else return a;}
int gcd(int a,int b){ return (b == 0) ? a : gcd(b, a % b);}
inline int lcm(int a,int b){ return a / gcd(a, b) * b;}
inline int normalize(int x,int mod){ x %= mod; if (x < 0) x += mod; return x;}

int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
string abc="abcdefghijklmnopqrstuvwxyz";
const double PI=acosl(-1);
const int mod = 1000*1000*1000+7;
//const int mod = 998244353;
const int inf = 1e18 +5;

//a and b are assumed to be taken modulo p
inline int add(int a, int b, int p = mod){ int c = a + b; if(c >= p) c -= p; return c; }
inline int sub(int a, int b, int p = mod){ int c = a - b; if(c < 0) c += p; return c; }
inline int mul(int a, int b, int p = mod){ return (a * 1ll * b) % p; }

// template<typename T>
// using ordered_set = tree<T,null_type,less<T>,rb_tree_tag,tree_order_statistics_node_update>;
//1. order_of_key(k) : number of elements strictly lesser than k
//2. find_by_order(k) : k-th element in the set
//To make it an ordered_multiset, use pairs of (value, time_of_insertion)
//to distinguish values which are similar.

int floor1(int n,int k){
    if(n%k == 0 || n >= 0)return n/k;
    return (n/k)-1;
}

int ceil1(int n,int k){
    return floor1(n+k-1,k);
}

int powm(int a, int b) {
    int res=1;
    while(b) {
        if(b&1)
            res=(res*a)%mod;
        a=(a*a)%mod;
        b>>=1;
    }
    return res;
}

const int N = 1e6 + 5;

int n,m;
string s[N];
string t[N];

int cache[N][(1<<3) +5]; // changes

int dp(int pos,int last){

    if(pos==n)
        return 0;

    int &ans=cache[pos][last];
    if(ans!=-1)
        return ans;

    ans=inf;

    fr(cur,0,1<<m){

        fr(i,0,m){

            if(i+1<m){

                int x1=((1<<i)&last!=0);
                int x2=((1<<(i+1))&last!=0);
                int x3=((1<<i)&cur!=0);
                int x4=((1<<(i+1))&cur!=0);
                int cnt=x1+x2+x3+x4;

                //cout<<pos<<" "<<last<<" "<<cur<<" "<<cnt<<endl;

                if(cnt%2){

                    int changes= (x3!=(s[pos][i]-'0')) + (x4!=(s[pos][i+1]-'0'));
                    ans=min(ans,changes+dp(pos+1,cur));
                }

            }

        }

    }

    return ans;

}

void solve(){

    cin>>n>>m;
    fr(i,0,n){
        cin>>s[i];
    }

    //fill(cache,-1);
    fr(i,0,n){
        fr(j,0,1<<m)
            cache[i][j]=-1;
    }

    if(min(n,m)>3){
        cout<<-1;
        return;
    }

    if(n<m){

        fr(i,0,m){
            t[i]="";
            fr(j,0,n){
                t[i]+=s[j][i];
            }
        }
        fr(i,0,m){
            s[i]=t[i];
        }
        n=n+m-(m=n);

    }

    int mn=n*m;

    if(m==4)
        cout<<-1;

    fr(i,0,1<<m){
        int ch=0;
        fr(j,0,m){
            if((1<<j)&i){
                if(s[0][j]=='0')
                    ++ch;
            }else{
                if(s[0][j]=='1')
                    ++ch;
            }

        }

        //cout<<ch<<" "<<i<<endl;

        mn=min(mn,ch+dp(1,i));
    }

    cout<<mn;

}

signed main() {
    fio;
    #ifndef ONLINE_JUDGE
        freopen("input.txt", "r", stdin);
        freopen("output.txt", "w", stdout);
        //freopen("error.txt", "w", stderr);
    #endif
    cout<<fixed<<setprecision(10);
    int t=1;
    //cin>>t;  // UNCOMMENT FOR TEST-CASES
    //precompute();
    int cnt=1;
    while(t--) {
        //cout<<"Case #"<<cnt++<<": ";
        solve();
    }
    return 0;
}


/*
 * Author    : raj1307 - Raj Singh
 * Date      : 10.10.2020
 */

#pragma GCC optimize("Ofast")
// #pragma GCC optimize("unroll-loops")
// #define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;

#define fio ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define fr(i, a, b) for(int i = (a); i < (b); ++i)
#define fb(i, b, a) for(int i = (b); i > (a); --i)
#define fill(x,y) memset(x,y,sizeof(x))
#define rr return
#define mp make_pair
#define pb push_back
#define sz(x) ((int)x.size())
#define int long long
//#define ll long long
#define ld long double
#define S second
#define F first
#define endl "\n"
#define Endl "\n"
#define all(v) (v).begin(), (v).end()
typedef pair<int, int> pii;
int max(int a,int b){if(a>b) return a; else return b;}
int min(int a,int b){if(a>b) return b; else return a;}
int gcd(int a,int b){ return (b == 0) ? a : gcd(b, a % b);}
inline int lcm(int a,int b){ return a / gcd(a, b) * b;}
inline int normalize(int x,int mod){ x %= mod; if (x < 0) x += mod; return x;}

int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
string abc="abcdefghijklmnopqrstuvwxyz";
const double PI=acosl(-1);
const int mod = 1000*1000*1000+7;
//const int mod = 998244353;
const int inf = 1e18 +5;

//a and b are assumed to be taken modulo p
inline int add(int a, int b, int p = mod){ int c = a + b; if(c >= p) c -= p; return c; }
inline int sub(int a, int b, int p = mod){ int c = a - b; if(c < 0) c += p; return c; }
inline int mul(int a, int b, int p = mod){ return (a * 1ll * b) % p; }

// template<typename T>
// using ordered_set = tree<T,null_type,less<T>,rb_tree_tag,tree_order_statistics_node_update>;
//1. order_of_key(k) : number of elements strictly lesser than k
//2. find_by_order(k) : k-th element in the set
//To make it an ordered_multiset, use pairs of (value, time_of_insertion)
//to distinguish values which are similar.

int floor1(int n,int k){
    if(n%k == 0 || n >= 0)return n/k;
    return (n/k)-1;
}

int ceil1(int n,int k){
    return floor1(n+k-1,k);
}

int powm(int a, int b) {
    int res=1;
    while(b) {
        if(b&1)
            res=(res*a)%mod;
        a=(a*a)%mod;
        b>>=1;
    }
    return res;
}

const int N = 1e6 + 5;

int n,m;
string s[N];
string t[N];

int cache[N][(1<<3) +5]; // changes

int dp(int pos,int last){

    if(pos==n)
        return 0;

    int &ans=cache[pos][last];
    if(ans!=-1)
        return ans;

    ans=inf;

    fr(cur,0,1<<m){

        fr(i,0,m){

            if(i+1<m){

                int x1=((1<<i)&last!=0);
                int x2=((1<<(i+1))&last!=0);
                int x3=((1<<i)&cur!=0);
                int x4=((1<<(i+1))&cur!=0);
                int cnt=x1+x2+x3+x4;

                //cout<<pos<<" "<<last<<" "<<cur<<" "<<cnt<<endl;

                if(cnt%2){

                    int changes= (x1!=(s[pos][i]-'0')) + (x1!=(s[pos][i+1]-'0'));
                    ans=min(ans,changes+dp(pos+1,cur));
                }

            }

        }

    }

    return ans;

}

void solve(){

    cin>>n>>m;
    fr(i,0,n){
        cin>>s[i];
    }

    //fill(cache,-1);
    fr(i,0,n){
        fr(j,0,1<<m)
            cache[i][j]=-1;
    }

    if(min(n,m)>3){
        cout<<-1;
        return;
    }

    if(n<m){

        fr(i,0,m){
            fr(j,0,n){
                t[i]+=s[j][i];
            }
        }
        fr(i,0,m){
            s[i]=t[i];
        }
        n=n+m-(m=n);
        cout<<n<<" "<<m<<endl;

    }

    int mn=n*m;

    if(m==4)
        cout<<-1;

    fr(i,0,1<<m){
        int ch=0;
        fr(j,0,m){
            if((1<<j)&i){
                if(s[0][j]=='0')
                    ++ch;
            }else{
                if(s[0][j]=='1')
                    ++ch;
            }

        }

        //cout<<ch<<" "<<i<<endl;

        mn=min(mn,ch+dp(1,i));
    }

    cout<<mn;

}

signed main() {
    fio;
    #ifndef ONLINE_JUDGE
        freopen("input.txt", "r", stdin);
        freopen("output.txt", "w", stdout);
        //freopen("error.txt", "w", stderr);
    #endif
    cout<<fixed<<setprecision(10);
    int t=1;
    //cin>>t;  // UNCOMMENT FOR TEST-CASES
    //precompute();
    int cnt=1;
    while(t--) {
        //cout<<"Case #"<<cnt++<<": ";
        solve();
    }
    return 0;
}


/*
 * Author    : raj1307 - Raj Singh
 * Date      : 10.10.2020
 */

#pragma GCC optimize("Ofast")
// #pragma GCC optimize("unroll-loops")
// #define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;

#define fio ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define fr(i, a, b) for(int i = (a); i < (b); ++i)
#define fb(i, b, a) for(int i = (b); i > (a); --i)
#define fill(x,y) memset(x,y,sizeof(x))
#define rr return
#define mp make_pair
#define pb push_back
#define sz(x) ((int)x.size())
#define int long long
//#define ll long long
#define ld long double
#define S second
#define F first
#define endl "\n"
#define Endl "\n"
#define all(v) (v).begin(), (v).end()
typedef pair<int, int> pii;
int max(int a,int b){if(a>b) return a; else return b;}
int min(int a,int b){if(a>b) return b; else return a;}
int gcd(int a,int b){ return (b == 0) ? a : gcd(b, a % b);}
inline int lcm(int a,int b){ return a / gcd(a, b) * b;}
inline int normalize(int x,int mod){ x %= mod; if (x < 0) x += mod; return x;}

int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
string abc="abcdefghijklmnopqrstuvwxyz";
const double PI=acosl(-1);
const int mod = 1000*1000*1000+7;
//const int mod = 998244353;
const int inf = 1e18 +5;

//a and b are assumed to be taken modulo p
inline int add(int a, int b, int p = mod){ int c = a + b; if(c >= p) c -= p; return c; }
inline int sub(int a, int b, int p = mod){ int c = a - b; if(c < 0) c += p; return c; }
inline int mul(int a, int b, int p = mod){ return (a * 1ll * b) % p; }

// template<typename T>
// using ordered_set = tree<T,null_type,less<T>,rb_tree_tag,tree_order_statistics_node_update>;
//1. order_of_key(k) : number of elements strictly lesser than k
//2. find_by_order(k) : k-th element in the set
//To make it an ordered_multiset, use pairs of (value, time_of_insertion)
//to distinguish values which are similar.

int floor1(int n,int k){
    if(n%k == 0 || n >= 0)return n/k;
    return (n/k)-1;
}

int ceil1(int n,int k){
    return floor1(n+k-1,k);
}

int powm(int a, int b) {
    int res=1;
    while(b) {
        if(b&1)
            res=(res*a)%mod;
        a=(a*a)%mod;
        b>>=1;
    }
    return res;
}

const int N = 1e6 + 5;

int n,m;
string s[N];
string t[N];

int cache[N][(1<<3) +5]; // changes

int dp(int pos,int last){

    if(pos==n)
        return 0;

    int &ans=cache[pos][last];
    if(ans!=-1)
        return ans;

    ans=inf;

    fr(cur,0,1<<m){

        fr(i,0,m){

            if(i+1<m){

                int x1=(((1<<i)&last)!=0);
                int x2=(((1<<(i+1))&last)!=0);
                int x3=(((1<<i)&cur)!=0);
                int x4=(((1<<(i+1))&cur)!=0);
                int cnt=x1+x2+x3+x4;

                if(cnt%2){

                    int changes= 0;

                    if(x3!=(s[pos][i]-'0'))
                        ++changes;
                    if(x4!=(s[pos][i+1]-'0'));
                        ++changes;

                    ans=min(ans,changes+dp(pos+1,cur));
                }

            }

        }

    }

    return ans;

}

void solve(){

    cin>>n>>m;
    fr(i,0,n){
        cin>>s[i];
    }

    //fill(cache,-1);
    fr(i,0,n){
        fr(j,0,1<<m)
            cache[i][j]=-1;
    }

    if(min(n,m)>3){
        cout<<-1;
        return;
    }

    if(n<m){

        fr(i,0,m){
            t[i]="";
            fr(j,0,n){
                t[i]+=s[j][i];
            }
        }
        fr(i,0,m){
            s[i]=t[i];
        }
        n=n+m-(m=n);

    }

    int mn=n*m;

    fr(i,0,1<<m){
        int ch=0;
        fr(j,0,m){
            if((1<<j)&i){
                if(s[0][j]=='0')
                    ++ch;
            }else{
                if(s[0][j]=='1')
                    ++ch;
            }

        }

        //cout<<ch<<" "<<i<<endl;

        mn=min(mn,ch+dp(1,i));
        //cout<<mn<<endl;
    }

    cout<<mn;

}

signed main() {
    fio;
    #ifndef ONLINE_JUDGE
        freopen("input.txt", "r", stdin);
        freopen("output.txt", "w", stdout);
        //freopen("error.txt", "w", stderr);
    #endif
    cout<<fixed<<setprecision(10);
    int t=1;
    //cin>>t;  // UNCOMMENT FOR TEST-CASES
    //precompute();
    int cnt=1;
    while(t--) {
        //cout<<"Case #"<<cnt++<<": ";
        solve();
    }
    return 0;
}


/*
 * Author    : raj1307 - Raj Singh
 * Date      : 10.10.2020
 */

#pragma GCC optimize("Ofast")
// #pragma GCC optimize("unroll-loops")
// #define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;

#define fio ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define fr(i, a, b) for(int i = (a); i < (b); ++i)
#define fb(i, b, a) for(int i = (b); i > (a); --i)
#define fill(x,y) memset(x,y,sizeof(x))
#define rr return
#define mp make_pair
#define pb push_back
#define sz(x) ((int)x.size())
#define int long long
//#define ll long long
#define ld long double
#define S second
#define F first
#define endl "\n"
#define Endl "\n"
#define all(v) (v).begin(), (v).end()
typedef pair<int, int> pii;
int max(int a,int b){if(a>b) return a; else return b;}
int min(int a,int b){if(a>b) return b; else return a;}
int gcd(int a,int b){ return (b == 0) ? a : gcd(b, a % b);}
inline int lcm(int a,int b){ return a / gcd(a, b) * b;}
inline int normalize(int x,int mod){ x %= mod; if (x < 0) x += mod; return x;}

int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
string abc="abcdefghijklmnopqrstuvwxyz";
const double PI=acosl(-1);
const int mod = 1000*1000*1000+7;
//const int mod = 998244353;
const int inf = 1e18 +5;

//a and b are assumed to be taken modulo p
inline int add(int a, int b, int p = mod){ int c = a + b; if(c >= p) c -= p; return c; }
inline int sub(int a, int b, int p = mod){ int c = a - b; if(c < 0) c += p; return c; }
inline int mul(int a, int b, int p = mod){ return (a * 1ll * b) % p; }

// template<typename T>
// using ordered_set = tree<T,null_type,less<T>,rb_tree_tag,tree_order_statistics_node_update>;
//1. order_of_key(k) : number of elements strictly lesser than k
//2. find_by_order(k) : k-th element in the set
//To make it an ordered_multiset, use pairs of (value, time_of_insertion)
//to distinguish values which are similar.

int floor1(int n,int k){
    if(n%k == 0 || n >= 0)return n/k;
    return (n/k)-1;
}

int ceil1(int n,int k){
    return floor1(n+k-1,k);
}

int powm(int a, int b) {
    int res=1;
    while(b) {
        if(b&1)
            res=(res*a)%mod;
        a=(a*a)%mod;
        b>>=1;
    }
    return res;
}

const int N = 1e6 + 5;

int n,m;
string s[N];
string t[N];

int cache[N][(1<<3) +5]; // changes

int dp(int pos,int last){

    if(pos==n)
        return 0;

    int &ans=cache[pos][last];
    if(ans!=-1)
        return ans;

    ans=inf;

    fr(cur,0,1<<m){

        int flag=1;

        fr(i,0,m){

            if(i+1<m){

                int cnt=0;

                if(((1<<i)&last)!=0) ++cnt;
                if(((1<<(i+1))&last)!=0)++cnt;
                if(((1<<i)&cur)!=0) ++cnt;
                if(((1<<(i+1))&cur)!=0) ++cnt;

                // int x1=(((1<<i)&last)!=0);
                // int x2=(((1<<(i+1))&last)!=0);
                // int x3=(((1<<i)&cur)!=0);
                // int x4=(((1<<(i+1))&cur)!=0);
                //int cnt=x1+x2+x3+x4;

                if(cnt%2==0){
                    flag=0;
                    break;
                }

                // if(cnt%2){

                //     int changes= 0;

                //     if(x3!=(s[pos][i]-'0'))
                //         ++changes;
                //     if(x4!=(s[pos][i+1]-'0'));
                //         ++changes;

                //     ans=min(ans,changes+dp(pos+1,cur));
                // }

            }

        }

        if(flag){

            int changes= 0;

            fr(i,0,m){
                if((1<<i)&cur){
                    if(s[pos][i]=='0')
                        ++changes;
                    }else{
                        if(s[pos][i]=='1')
                            ++changes;
                    }
            }

            ans=min(ans,changes+dp(pos+1,cur));
        }

    }

    return ans;

}

void solve(){

    cin>>n>>m;
    fr(i,0,n){
        cin>>s[i];
    }

    //fill(cache,-1);

    if(min(n,m)>3){
        cout<<-1;
        return;
    }

    if(n<m){

        fr(i,0,m){
            t[i]="";
            fr(j,0,n){
                t[i]+=s[j][i];
            }
        }
        fr(i,0,m){
            s[i]=t[i];
        }
        n=n+m-(m=n);
        // fr(i,0,n) cout<<s[i]<<endl;
        // cout<<n<<" "<<m<<endl;

    }

    fr(i,0,n){
        fr(j,0,1<<m)
            cache[i][j]=-1;
    }

    int mn=n*m;

    fr(i,0,1<<m){
        int ch=0;
        fr(j,0,m){
            if((1<<j)&i){
                if(s[0][j]=='0')
                    ++ch;
            }else{
                if(s[0][j]=='1')
                    ++ch;
            }

        }

        //cout<<ch<<" "<<i<<endl;

        mn=min(mn,ch+dp(1,i));
        //cout<<mn<<endl;
    }

    cout<<mn;

}

signed main() {
    fio;
    #ifndef ONLINE_JUDGE
        freopen("input.txt", "r", stdin);
        freopen("output.txt", "w", stdout);
        //freopen("error.txt", "w", stderr);
    #endif
    cout<<fixed<<setprecision(10);
    int t=1;
    //cin>>t;  // UNCOMMENT FOR TEST-CASES
    //precompute();
    int cnt=1;
    while(t--) {
        //cout<<"Case #"<<cnt++<<": ";
        solve();
    }
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define dbg(x) cout <<#x<<":"<<x<<endl;
#define dbgpo(x,y) cout<<"("<<x<<","<<y<<")"<<endl;
#define fast ios_base::sync_with_stdio(false); cin.tie(NULL)
#define pb push_back
#define eb emplace_back
#define f first
#define s second
#define mp make_pair
#define pii pair<int,int>
#define pll pair<ll,ll>
#define endl '\n'
#define mod 1000000007
// #define int long long

ll power(ll x,ll y, ll md=mod){ll res = 1;x%=md;while(y>0){if(y&1)res = (res*x)%md;x *= x; if(x>=md) x %= md; y >>= 1;}return res;}

const int M = 1000001;

int m,nr;

int dp[2][8];
vector<int> given(M);

int comp2[8][2] = {
  {1,2},  {0,3},  {0,3},  {1,2}
};

int comp3[8][2] = {
  {2,5},  {3,4},  {0,7},  {1,6},  {1,6},  {0,7},  {3,4},  {5,2}
};

void init(){
  char c;
  int h = 1<<(nr-1);
  for(int i=0;i<nr;i++,h>>=1){
    for(int j=0;j<m;j++){
      cin>>c;
      given[j] += (c - '0')*h;
    }
  }

  return;
}

int solve(){
  init();

  int mx = 1<<nr;

  for(int mask=0;mask<mx;mask++){
    dp[0][mask] = __builtin_popcount(given[0]^mask);
  }

  if(nr==3){
    for(int i=1;i<m;i++){
      for(int mask=0;mask<mx;mask++){
          int m1 = comp3[mask][0], m2 = comp3[mask][1];
          dp[1][mask] =  min(dp[0][m1],dp[0][m2]) + __builtin_popcount(given[i]^mask);
      }
      for(int mask=0;mask<mx;mask++) dp[0][mask] = dp[1][mask];
    }
  }
  else{
    for(int i=1;i<m;i++){
      for(int mask=0;mask<mx;mask++){
          int m1 = comp2[mask][0], m2 = comp2[mask][1];
          dp[1][mask] =  min(dp[0][m1],dp[0][m2]) + __builtin_popcount(given[i]^mask);
      }
      for(int mask=0;mask<mx;mask++) dp[0][mask] = dp[1][mask];
    }
  }

  int ans = 1e6;
  for(int mask=0;mask<mx;mask++)
    ans = min(ans,dp[0][mask]);

  return ans;
}

signed main(){
  // fast;
  cin>>nr>>m;

  switch(nr){
    case 1: cout<<0;
            break;
    case 2: cout<<solve();
            break;
    case 3: cout<<solve();
            break;
    default: cout<< -1;
  }

}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define dbg(x) cout <<#x<<":"<<x<<endl;
#define dbgpo(x,y) cout<<"("<<x<<","<<y<<")"<<endl;
#define fast ios_base::sync_with_stdio(false); cin.tie(NULL)
#define pb push_back
#define eb emplace_back
#define f first
#define s second
#define mp make_pair
#define pii pair<int,int>
#define pll pair<ll,ll>
#define endl '\n'
#define mod 1000000007
#define int long long

ll power(ll x,ll y, ll md=mod){ll res = 1;x%=md;while(y>0){if(y&1)res = (res*x)%md;x *= x; if(x>=md) x %= md; y >>= 1;}return res;}

const int M = 1000001;

int m,nr;

int dp[M][8];
vector<int> given(M);

int comp2[8][2] = {
  {1,2},  {0,3},  {0,3},  {1,2}
};

int comp3[8][2] = {
  {2,5},  {3,4},  {0,7},  {1,6},  {1,6},  {0,7},  {3,4},  {5,2}
};

void init(){
  char c;
  int h = 1<<(nr-1);
  for(int i=0;i<nr;i++,h>>=1){
    for(int j=0;j<m;j++){
      cin>>c;
      given[j] += (c - '0')*h;
    }
  }

  return;
}

int solve(){
  init();

  int mx = 1<<nr;

  for(int mask=0;mask<mx;mask++){
    dp[0][mask] = __builtin_popcount(given[0]^mask);
  }

  if(nr==3){
    for(int i=1;i<m;i++){
      for(int mask=0;mask<mx;mask++){
          int m1 = comp3[mask][0], m2 = comp3[mask][1];
          dp[i][mask] =  min(dp[i-1][m1],dp[i-1][m2]) + __builtin_popcount(given[i]^mask);
      }
    }
  }
  else{
    for(int i=1;i<m;i++){
      for(int mask=0;mask<mx;mask++){
          int m1 = comp2[mask][0], m2 = comp2[mask][1];
          dp[i][mask] =  min(dp[i-1][m1],dp[i-1][m2]) + __builtin_popcount(given[i]^mask);
      }
    }
  }

  int ans = 1e6;
  for(int mask=0;mask<mx;mask++)
    ans = min(ans,dp[nr-1][mask]);

  return ans;
}

signed main(){
  // fast;
  cin>>nr>>m;

  switch(nr){
    case 1: cout<<0;
            break;
    case 2: cout<<solve();
            break;
    case 3: cout<<solve();
            break;
    default: cout<< -1;
  }

}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define dbg(x) cout <<#x<<":"<<x<<endl;
#define dbgpo(x,y) cout<<"("<<x<<","<<y<<")"<<endl;
#define fast ios_base::sync_with_stdio(false); cin.tie(NULL)
#define pb push_back
#define eb emplace_back
#define f first
#define s second
#define mp make_pair
#define pii pair<int,int>
#define pll pair<ll,ll>
#define endl '\n'
#define mod 1000000007
#define int long long

ll power(ll x,ll y, ll md=mod){ll res = 1;x%=md;while(y>0){if(y&1)res = (res*x)%md;x *= x; if(x>=md) x %= md; y >>= 1;}return res;}

const int M = 1000001;

int m,nr;

int dp[M][8];
vector<int> given(M);

int comp2[8][2] = {
  {1,2},  {0,3},  {0,3},  {1,2}
};

int comp3[8][2] = {
  {2,5},  {3,4},  {0,7},  {1,6},  {1,6},  {0,7},  {3,4},  {5,2}
};

void init(){
  char c;
  int h = 1<<(nr-1);
  for(int i=0;i<nr;i++,h>>=1){
    for(int j=0;j<m;j++){
      cin>>c;
      given[j] += (c - '0')*h;
    }
  }

  return;
}

int solve(){
  init();

  int mx = 1<<nr;

  for(int mask=0;mask<mx;mask++){
    dp[0][mask] = __builtin_popcount(given[0]^mask);
  }

  if(nr==3){
    for(int i=1;i<m;i++){
      for(int mask=0;mask<mx;mask++){
          int m1 = comp3[mask][0], m2 = comp3[mask][1];
          dp[i][mask] =  min(dp[i-1][m1],dp[i-1][m2]) + __builtin_popcount(given[i]^mask);
      }
    }
  }
  else{
    for(int i=1;i<m;i++){
      for(int mask=0;mask<mx;mask++){
          int m1 = comp2[mask][0], m2 = comp2[mask][1];
          dp[i][mask] =  min(dp[i-1][m1],dp[i-1][m2]) + __builtin_popcount(given[i]^mask);
      }
    }
  }

  int ans = 1e6;
  for(int mask=0;mask<mx;mask++)
    ans = min(ans,dp[m-1][mask]);

  return ans;
}

signed main(){
  // fast;
  cin>>nr>>m;

  switch(nr){
    case 1: cout<<0;
            break;
    case 2: cout<<solve();
            break;
    case 3: cout<<solve();
            break;
    default: cout<< -1;
  }

}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define dbg(x) cout <<#x<<":"<<x<<endl;
#define dbgpo(x,y) cout<<"("<<x<<","<<y<<")"<<endl;
#define fast ios_base::sync_with_stdio(false); cin.tie(NULL)
#define pb push_back
#define eb emplace_back
#define f first
#define s second
#define mp make_pair
#define pii pair<int,int>
#define pll pair<ll,ll>
#define endl '\n'
#define mod 1000000007
// #define int long long

const int M = 1000001;

int m,nr;

int dp[2][8];
vector<int> given(M);

int comp2[4][2] = {
  {1,2},  {0,3},  {0,3},  {1,2}
};

int comp3[8][2] = {
  {2,5},  {3,4},  {0,7},  {1,6},  {1,6},  {0,7},  {3,4},  {5,2}
};

inline int solve(){
  char c;
  int h = 1<<(nr-1);
  for(int i=0;i<nr;i++,h>>=1){
    for(int j=0;j<m;j++){
      cin>>c;
      given[j] += (c - '0')*h;
    }
  }

  int mx = 1<<nr;

  for(int mask=0;mask<mx;mask++){
    dp[0][mask] = __builtin_popcount(given[0]^mask);
  }

  if(nr==3){
    for(int i=1;i<m;i++){
      for(int mask=0;mask<mx;mask++){
          int m1 = comp3[mask][0], m2 = comp3[mask][1];
          dp[1][mask] =  min(dp[0][m1],dp[0][m2]) + __builtin_popcount(given[i]^mask);
      }
      for(int mask=0;mask<mx;mask++) dp[0][mask] = dp[1][mask];
    }
  }
  else{
    for(int i=1;i<m;i++){
      for(int mask=0;mask<mx;mask++){
          int m1 = comp2[mask][0], m2 = comp2[mask][1];
          dp[1][mask] =  min(dp[0][m1],dp[0][m2]) + __builtin_popcount(given[i]^mask);
      }
      for(int mask=0;mask<mx;mask++) dp[0][mask] = dp[1][mask];
    }
  }

  int ans = 1e6;
  for(int mask=0;mask<mx;mask++)
    ans = min(ans,dp[0][mask]);

  return ans;
}

signed main(){
  // fast;
  cin>>nr>>m;

  switch(nr){
    case 1: cout<<0;
            break;
    case 2: cout<<solve();
            break;
    case 3: cout<<solve();
            break;
    default: cout<< -1;
  }

}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define dbg(x) cout <<#x<<":"<<x<<endl;
#define dbgpo(x,y) cout<<"("<<x<<","<<y<<")"<<endl;
#define fast ios_base::sync_with_stdio(false); cin.tie(NULL)
#define pb push_back
#define eb emplace_back
#define f first
#define s second
#define mp make_pair
#define pii pair<int,int>
#define pll pair<ll,ll>
#define endl '\n'
#define mod 1000000007
// #define int long long

const int M = 1000001;

int m,nr;

int dp[2][8];
vector<int> given(M);

int comp2[4][2] = {
  {1,2},  {0,3},  {0,3},  {1,2}
};

int comp3[8][2] = {
  {2,5},  {3,4},  {0,7},  {1,6},  {1,6},  {0,7},  {3,4},  {5,2}
};

inline int solve(){
  char c;
  int h = 1<<(nr-1);
  for(int i=0;i<nr;i++,h>>=1){
    for(int j=0;j<m;j++){
      cin>>c;
      given[j] += (c - '0')*h;
    }
  }

  int mx = 1<<nr;

  for(int mask=0;mask<mx;mask++){
    dp[0][mask] = __builtin_popcount(given[0]^mask);
  }

  if(nr==3){
    for(int i=1;i<m;i++){
      for(int mask=0;mask<mx;mask++){
          int m1 = comp3[mask][0], m2 = comp3[mask][1];
          dp[1][mask] =  min(dp[0][m1],dp[0][m2]) + __builtin_popcount(given[i]^mask);
      }
      for(int mask=0;mask<mx;mask++) dp[0][mask] = dp[1][mask];
    }
  }
  else{
    for(int i=1;i<m;i++){
      for(int mask=0;mask<mx;mask++){
          int m1 = comp2[mask][0], m2 = comp2[mask][1];
          dp[1][mask] =  min(dp[0][m1],dp[0][m2]) + __builtin_popcount(given[i]^mask);
      }
      for(int mask=0;mask<mx;mask++) dp[0][mask] = dp[1][mask];
    }
  }

  int ans = 1e6;
  for(int mask=0;mask<mx;mask++)
    ans = min(ans,dp[0][mask]);

  return ans;
}

signed main(){
  // fast;
  cin>>nr>>m;

  if(nr==1)
    cout<<0;
  else if(nr>=4)
    cout<<-1;
  else
    cout<<solve();

}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define dbg(x) cout <<#x<<":"<<x<<endl;
#define dbgpo(x,y) cout<<"("<<x<<","<<y<<")"<<endl;
#define fast ios_base::sync_with_stdio(false); cin.tie(NULL)
#define pb push_back
#define eb emplace_back
#define f first
#define s second
#define mp make_pair
#define pii pair<int,int>
#define pll pair<ll,ll>
#define endl '\n'
#define mod 1000000007
#define int long long

ll power(ll x,ll y, ll md=mod){ll res = 1;x%=md;while(y>0){if(y&1)res = (res*x)%md;x *= x; if(x>=md) x %= md; y >>= 1;}return res;}

const int M = 1000001;

int m,nr;

int dp[2][8];
vector<int> given(M);

int comp2[8][2] = {
  {1,2},  {0,3},  {0,3},  {1,2}
};

int comp3[8][2] = {
  {2,5},  {3,4},  {0,7},  {1,6},  {1,6},  {0,7},  {3,4},  {5,2}
};

void init(){
  char c;
  int h = 1<<(nr-1);
  for(int i=0;i<nr;i++,h>>=1){
    for(int j=0;j<m;j++){
      cin>>c;
      given[j] += (c - '0')*h;
    }
  }

  return;
}

int solve(){
  init();

  int mx = 1<<nr;

  for(int mask=0;mask<mx;mask++){
    dp[0][mask] = __builtin_popcount(given[0]^mask);
  }

  if(nr==3){
    for(int i=1;i<m;i++){
      for(int mask=0;mask<mx;mask++){
          int m1 = comp3[mask][0], m2 = comp3[mask][1];
          dp[1][mask] =  min(dp[0][m1],dp[0][m2]) + __builtin_popcount(given[i]^mask);
      }
      for(int mask=0;mask<mx;mask++) dp[0][mask] = dp[1][mask];
    }
  }
  else{
    for(int i=1;i<m;i++){
      for(int mask=0;mask<mx;mask++){
          int m1 = comp2[mask][0], m2 = comp2[mask][1];
          dp[1][mask] =  min(dp[0][m1],dp[0][m2]) + __builtin_popcount(given[i]^mask);
      }
      for(int mask=0;mask<mx;mask++) dp[0][mask] = dp[1][mask];
    }
  }

  int ans = 1e6;
  for(int mask=0;mask<mx;mask++)
    ans = min(ans,dp[0][mask]);

  return ans;
}

signed main(){
  // fast;
  cin>>nr>>m;

  switch(nr){
    case 1: cout<<0;
            break;
    case 2: cout<<solve();
            break;
    case 3: cout<<solve();
            break;
    default: cout<< -1;
  }

}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define dbg(x) cout <<#x<<":"<<x<<endl;
#define dbgpo(x,y) cout<<"("<<x<<","<<y<<")"<<endl;
#define fast ios_base::sync_with_stdio(false); cin.tie(NULL)
#define pb push_back
#define eb emplace_back
#define f first
#define s second
#define mp make_pair
#define pii pair<int,int>
#define pll pair<ll,ll>
#define endl '\n'
#define mod 1000000007
// #define int long long

const int M = 1000001;

int m,nr;

int dp[2][8];
vector<int> given(M);

int comp2[4][2] = {
  {1,2},  {0,3},  {0,3},  {1,2}
};

int comp3[8][2] = {
  {2,5},  {3,4},  {0,7},  {1,6},  {1,6},  {0,7},  {3,4},  {5,2}
};

inline int solve(){
  char c;
  int h = 1<<(nr-1);
  for(int i=0;i<nr;i++,h>>=1){
    for(int j=0;j<m;j++){
      cin>>c;
      given[j] += (c - '0')*h;
    }
  }

  int mx = 1<<nr;

  for(int mask=0;mask<mx;mask++){
    dp[0][mask] = __builtin_popcount(given[0]^mask);
  }

  if(nr==3){
    for(int i=1;i<m;i++){
      for(int mask=0;mask<mx;mask++){
          int m1 = comp3[mask][0], m2 = comp3[mask][1];
          dp[1][mask] =  min(dp[0][m1],dp[0][m2]) + __builtin_popcount(given[i]^mask);
      }
      for(int mask=0;mask<mx;mask++) dp[0][mask] = dp[1][mask];
    }
  }
  else{
    for(int i=1;i<m;i++){
      for(int mask=0;mask<mx;mask++){
          int m1 = comp2[mask][0], m2 = comp2[mask][1];
          dp[1][mask] =  min(dp[0][m1],dp[0][m2]) + __builtin_popcount(given[i]^mask);
      }
      for(int mask=0;mask<mx;mask++) dp[0][mask] = dp[1][mask];
    }
  }

  int ans = 1e6;
  for(int mask=0;mask<mx;mask++)
    ans = min(ans,dp[0][mask]);

  return ans;
}

signed main(){
   fast;
  cin>>nr>>m;

  if(nr==1)
    cout<<0;
  else if(nr>=4)
    cout<<-1;
  else
    cout<<solve();

}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define dbg(x) cout <<#x<<":"<<x<<endl;
#define dbgpo(x,y) cout<<"("<<x<<","<<y<<")"<<endl;
#define fast ios_base::sync_with_stdio(false); cin.tie(NULL)
#define pb push_back
#define eb emplace_back
#define f first
#define s second
#define mp make_pair
#define pii pair<int,int>
#define pll pair<ll,ll>
#define endl '\n'
#define mod 1000000007
// #define int long long

const int M = 1000001;

int m,nr;

int dp[2][8];
vector<int> given(M);

int comp2[4][2] = {
  {1,2},  {0,3},  {0,3},  {1,2}
};

int comp3[8][2] = {
  {2,5},  {3,4},  {0,7},  {1,6},  {1,6},  {0,7},  {3,4},  {5,2}
};

inline int solve(){
  char c;
  int h = 1<<(nr-1);
  for(int i=0;i<nr;i++,h>>=1){
    for(int j=0;j<m;j++){
      cin>>c;
      given[j] += (c - '0')*h;
    }
  }

  int mx = 1<<nr;

  for(int mask=0;mask<mx;mask++){
    dp[0][mask] = __builtin_popcount(given[0]^mask);
  }

  if(nr==3){
    for(int i=1;i<m;i++){
      for(int mask=0;mask<mx;mask++){
          int m1 = comp3[mask][0], m2 = comp3[mask][1];
          dp[1][mask] =  min(dp[0][m1],dp[0][m2]) + __builtin_popcount(given[i]^mask);
      }
      for(int mask=0;mask<mx;mask++) dp[0][mask] = dp[1][mask];
    }
  }
  else{
    for(int i=1;i<m;i++){
      for(int mask=0;mask<mx;mask++){
          int m1 = comp2[mask][0], m2 = comp2[mask][1];
          dp[1][mask] =  min(dp[0][m1],dp[0][m2]) + __builtin_popcount(given[i]^mask);
      }
      for(int mask=0;mask<mx;mask++) dp[0][mask] = dp[1][mask];
    }
  }

  int ans = 1e6;
  for(int mask=0;mask<mx;mask++)
    ans = min(ans,dp[0][mask]);

  return ans;
}

signed main(){
  // fast;
  cin>>nr>>m;

  if(nr==1)
    cout<<0;
  else if(nr==4)
    cout<<-1;
  else
    cout<<solve();

}


#include<bits/stdc++.h>
using namespace std;

#define all(a) a.begin() , a.end()
#define print(x)   cout<<x<<"\n";
#define pb push_back

template <typename T>
ostream& operator<<(ostream& os, const vector<T>& v) {
    os << "["; for (int i = 0; i < v.size(); ++i) { os << v[i]; if (i != v.size() - 1) os << ", "; } os << "]\n"; return os;
}
template <typename T>
ostream& operator<<(ostream& os, const set<T>& v) {
    os << "["; for (auto it : v) {os << it; if (it != *v.rbegin())os << ", ";} os << "]\n"; return os;
}
template <typename T, typename S>
ostream& operator<<(ostream& os, const map<T, S>& v) {
    for (auto it : v)os << it.first << " : " << it.second << "\n"; return os;
}
template <typename T, typename S>
ostream& operator<<(ostream& os, const pair<T, S>& v) {
    os << "("; os << v.first << ", " << v.second << ")"; return os;
}
void go() {
    cin.tie(nullptr) -> sync_with_stdio(false);
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
}
#define int long long
int32_t main() {
    go();
    int n, m;
    cin >> n >> m;
    if (n >= 4 and m >= 4) {
        cout << -1;
        return 0;
    }
    vector<string> s(n);
    for (int i = 0; i < n; i++) {
        cin >> s[i];
    }
    vector<vector<int>> a(8, vector<int>(m, 0));    //a=wide
    vector<vector<int>> b(n, vector<int>(8, 0));
    a[0][0] = 1;
    a[0][1] = 1;
    b[0][0] = 1;
    b[0][1] = 1;
    for (int i = 2; i < m; i++) {
        a[0][i] = a[0][i - 2] ^ 1;
    }
    for (int i = 2; i < 8; i++) {
        b[0][i] = b[0][i - 2] ^ 1;
    }
    for (int i = 1; i < 8; i++) {
        for (int j = 0; j < m; j++) {
            a[i][j] = a[i - 1][(j + 1) % m];
        }
    }
    for (int i = 1; i < n; i++) {
        for (int j = 0; j < 8; j++) {
            b[i][j] = b[i - 1][(j + 1) % 8];
        }
    }
    print(a);
    print(b)
    int ans = 1e9;
    if (n >= 4) {
        int tt = 0;                               //b = long
        for (int k = 0; k < 4; k++) {
            for (int i = 0; i < n; i++) {
                for (int j = k; j < m + k; j++) {
                    if ((s[i][j - k] == '0' and b[i][j] == 1) or (s[i][j - k] == '1' and b[i][j] == 0))
                        tt++;
                }
            }
        }
        ans = min(ans, tt);
        tt = 0;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < 8; j++) {
                b[i][j] ^= 1;
            }
        }

        for (int k = 0; k < 4; k++) {
            for (int i = 0; i < n; i++) {
                for (int j = k; j < m + k; j++) {
                    if ((s[i][j - k] == '0' and b[i][j] == 1) or (s[i][j - k] == '1' and b[i][j] == 0))
                        tt++;
                }
            }
        }
        ans = min(ans, tt);
    }
    else {
        int tt = 0;
        for (int k = 0; k < 4; k++) {
            for (int i = k; i < n + k; i++) {
                for (int j = 0; j < m; j++) {
                    if ((s[i - k][j] == '0' and a[i][j] == 1) or (s[i - k][j] == '1' and a[i][j] == 0))
                        tt++;
                }
            }
        }
        ans = min(ans, tt);
        tt = 0;
        // for (int i = 0; i < m; i++) {
        //     for (int j = 0; j < )
        //     }
        for (int k = 0; k < 4; k++) {
            for (int i = k; i < n + k; i++) {
                for (int j = 0; j < m; j++) {
                    if ((s[i - k][j] == '0' and a[i][j] == 1) or (s[i - k][j] == '1' and a[i][j] == 0))
                        tt++;
                }
            }
        }
        ans = min(ans, tt);

    }
    cout << ans;
}


#include<bits/stdc++.h>
using namespace std;

#define all(a) a.begin() , a.end()
#define print(x)   cout<<x<<"\n";
#define pb push_back

template <typename T>
ostream& operator<<(ostream& os, const vector<T>& v) {
    os << "["; for (int i = 0; i < v.size(); ++i) { os << v[i]; if (i != v.size() - 1) os << ", "; } os << "]\n"; return os;
}
template <typename T>
ostream& operator<<(ostream& os, const set<T>& v) {
    os << "["; for (auto it : v) {os << it; if (it != *v.rbegin())os << ", ";} os << "]\n"; return os;
}
template <typename T, typename S>
ostream& operator<<(ostream& os, const map<T, S>& v) {
    for (auto it : v)os << it.first << " : " << it.second << "\n"; return os;
}
template <typename T, typename S>
ostream& operator<<(ostream& os, const pair<T, S>& v) {
    os << "("; os << v.first << ", " << v.second << ")"; return os;
}
void go() {
    cin.tie(nullptr) -> sync_with_stdio(false);
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
}
int32_t main() {
    go();
    int n, m;
    cin >> n >> m;
    if (n >= 4 and m >= 4) {
        cout << -1;
        return 0;
    }
    vector<string> s(n);
    for (int i = 0; i < n; i++) {
        cin >> s[i];
    }
    int nn = n + 4;
    int mm = m + 4;
    vector<vector<int>> a(nn, vector<int>(mm, 0));   // a = wide
    a[0][0] = 1;
    a[0][1] = 1;
    for (int i = 2; i < mm; i++) {
        a[0][i] = a[0][i - 2] ^ 1;
    }
    for (int i = 1; i < nn; i++) {
        for (int j = 0; j < mm; j++) {
            if (j < 2) {
                a[i][j] = a[i - 1][(j + 1) % mm];
            }
            else
                a[i][j] = a[i][j - 2] ^ 1;
        }
    }
    // print(a);
    int ans = 1e9;
    int tt = 0;
    for (int kk = 0; kk < 4; kk++) {
        for (int k = 0; k < 4; k++) {
            tt = 0;
            for (int i = kk; i < n + kk; i++) {
                for (int j = k; j < m + k; j++) {
                    if ((s[i - kk][j - k] == '0' and a[i][j] == 1) or (s[i - kk][j - k] == '1' and a[i][j] == 0))
                        tt++;
                }
            }
            ans = min(ans, tt);
        }
    }
    tt = 0;
    for (int i = 0; i < nn; i++) {
        for (int j = 0; j < mm; j++) {
            a[i][j] ^= 1;
        }
    }
    for (int kk = 0; kk < 4; kk++) {
        for (int k = 0; k < 4; k++) {
            tt = 0;
            for (int i = kk; i < n + kk; i++) {
                for (int j = k; j < m + k; j++) {
                    if ((s[i - kk][j - k] == '0' and a[i][j] == 1) or (s[i - kk][j - k] == '1' and a[i][j] == 0))
                        tt++;
                }
            }
            ans = min(ans, tt);
        }
    }
    for (int i = 0; i < nn; i++) {
        reverse(all(a[i]));
    }
    for (int kk = 0; kk < 4; kk++) {
        for (int k = 0; k < 4; k++) {
            tt = 0;
            for (int i = kk; i < n + kk; i++) {
                for (int j = k; j < m + k; j++) {
                    if ((s[i - kk][j - k] == '0' and a[i][j] == 1) or (s[i - kk][j - k] == '1' and a[i][j] == 0))
                        tt++;
                }
            }
            ans = min(ans, tt);
        }
    }
    tt = 0;
    for (int i = 0; i < nn; i++) {
        for (int j = 0; j < mm; j++) {
            a[i][j] ^= 1;
        }
    }
    for (int kk = 0; kk < 4; kk++) {
        for (int k = 0; k < 4; k++) {
            tt = 0;
            for (int i = kk; i < n + kk; i++) {
                for (int j = k; j < m + k; j++) {
                    if ((s[i - kk][j - k] == '0' and a[i][j] == 1) or (s[i - kk][j - k] == '1' and a[i][j] == 0))
                        tt++;
                }
            }
            ans = min(ans, tt);
        }
    }
    cout << ans;
}


#include<bits/stdc++.h>
using namespace std;

#define all(a) a.begin() , a.end()
#define print(x)   cout<<x<<"\n";
#define pb push_back

template <typename T>
ostream& operator<<(ostream& os, const vector<T>& v) {
    os << "["; for (int i = 0; i < v.size(); ++i) { os << v[i]; if (i != v.size() - 1) os << ", "; } os << "]\n"; return os;
}
template <typename T>
ostream& operator<<(ostream& os, const set<T>& v) {
    os << "["; for (auto it : v) {os << it; if (it != *v.rbegin())os << ", ";} os << "]\n"; return os;
}
template <typename T, typename S>
ostream& operator<<(ostream& os, const map<T, S>& v) {
    for (auto it : v)os << it.first << " : " << it.second << "\n"; return os;
}
template <typename T, typename S>
ostream& operator<<(ostream& os, const pair<T, S>& v) {
    os << "("; os << v.first << ", " << v.second << ")"; return os;
}
void go() {
    cin.tie(nullptr) -> sync_with_stdio(false);
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
}
int32_t main() {
    go();
    int n, m;
    cin >> n >> m;
    if (n >= 4 and m >= 4) {
        cout << -1;
        return 0;
    }
    vector<string> s(n);
    for (int i = 0; i < n; i++) {
        cin >> s[i];
    }
    if (min(n, m) == 1) {
        cout << 0;
        return 0;
    }
    int ans = 1e9;
    if (min(n, m) == 2) {
        int tt = 0;
        if (n == 2) {
            for (int i = 0; i < m; i++) {
                int x = s[0][i] - '0' + s[1][i] - '0';
                if (i % 2 == 0 and x % 2 != 0) {
                    tt++;
                }
            }
            ans = min(ans, tt);
            tt = 0;
            for (int i = 0; i < m; i++) {
                int x = s[0][i] - '0' + s[1][i] - '0';
                if (i % 2 == 0 and x % 2 == 0) {
                    tt++;
                }
            }
            ans = min(ans, tt);
        }
        else {
            tt = 0;
            for (int i = 0; i < n; i++) {
                int x = s[i][0] - '0' + s[i][1] - '0';
                if (i % 2 == 0 and x % 2 == 0) {
                    tt++;
                }
            }
            ans = min(ans, tt);
            tt = 0;
            for (int i = 0; i < n; i++) {
                int x = s[i][0] - '0' + s[i][1] - '0';
                if (i % 2 == 0 and x % 2 != 0) {
                    tt++;
                }
            }
            ans = min(ans, tt);
        }
    }
    else {
        if (n == 3) {
            int tt = 0;
            for (int mask = 0; mask < (1 << 2); mask++) {
                tt = 0;

                // int a = ((mask >> 2) & 1);
                // int b = ((mask >> 1) & 1);
                // int c = ((mask >> 0) & 1);
                // int ups = a + b;
                // int dwn = b + c;

                int ups = (mask & 1);
                int dwn = ((mask >> 1) & 1);
                // cout << ups << ' ' << dwn << '\n';
                for (int i = 0; i < m; i++) {
                    int up   = s[0][i] - '0' + s[1][i] - '0';
                    int down = s[1][i] - '0' + s[2][i] - '0';
                    int pp = 0;
                    if (i % 2 == 0) {
                        pp += (ups  != (up % 2));
                        pp += (dwn != (down % 2));
                    }
                    else {
                        pp += ((up % 2)  == ups);
                        pp += ((down % 2) == dwn);
                    }
                    if (pp == 2)
                        --pp;
                    tt += pp;
                }
                ans = min(ans, tt);
            }
        }
        else {
            int tt = 0;
            for (int mask = 0; mask < (1 << 2); mask++) {
                int ff = (mask & 1);
                int ss = ((mask >> 1) & 1);
                for (int i = 0; i < n; i++) {
                    int lft = s[i][0] - '0' + s[i][1] - '0';
                    int ryt = s[i][1] - '0' + s[i][2] - '0';
                    int pp = 0;
                    if (i % 2 == 0) {
                        pp += (ff == lft % 2);
                        pp += (ss == ryt % 2);
                    }
                    else {
                        pp += (ff != lft % 2);
                        pp += (ss != ryt % 2);
                    }
                    if (pp == 2)
                        --pp;
                    tt += pp;
                }
                ans = min(ans, tt);
            }
        }
    }
    cout << ans;
}


#include<bits/stdc++.h>
using namespace std;

#define all(a) a.begin() , a.end()
#define print(x)   cout<<x<<"\n";
#define pb push_back

template <typename T>
ostream& operator<<(ostream& os, const vector<T>& v) {
    os << "["; for (int i = 0; i < v.size(); ++i) { os << v[i]; if (i != v.size() - 1) os << ", "; } os << "]\n"; return os;
}
template <typename T>
ostream& operator<<(ostream& os, const set<T>& v) {
    os << "["; for (auto it : v) {os << it; if (it != *v.rbegin())os << ", ";} os << "]\n"; return os;
}
template <typename T, typename S>
ostream& operator<<(ostream& os, const map<T, S>& v) {
    for (auto it : v)os << it.first << " : " << it.second << "\n"; return os;
}
template <typename T, typename S>
ostream& operator<<(ostream& os, const pair<T, S>& v) {
    os << "("; os << v.first << ", " << v.second << ")"; return os;
}
void go() {
    cin.tie(nullptr) -> sync_with_stdio(false);
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
}
int32_t main() {
    go();
    int n, m;
    cin >> n >> m;
    if (n >= 4 and m >= 4) {
        cout << -1;
        return 0;
    }
    vector<string> s(n);
    for (int i = 0; i < n; i++) {
        cin >> s[i];
    }
    int nn = n + 4;
    int mm = m + 4;
    vector<vector<int>> a(8, vector<int>(mm, 0));   //a=wide
    vector<vector<int>> b(nn, vector<int>(8, 0));
    a[0][0] = 1;
    a[0][1] = 1;
    b[0][0] = 1;
    b[0][1] = 1;
    for (int i = 2; i < mm; i++) {
        a[0][i] = a[0][i - 2] ^ 1;
    }
    for (int i = 2; i < 8; i++) {
        b[0][i] = b[0][i - 2] ^ 1;
    }
    for (int i = 1; i < 8; i++) {
        for (int j = 0; j < mm; j++) {
            if (j < 2) {
                a[i][j] = a[i - 1][(j + 1) % mm];
            }
            else
                a[i][j] = a[i][j - 2] ^ 1;
        }
    }
    for (int i = 1; i < nn; i++) {
        for (int j = 0; j < 8; j++) {
            if (j < 2)
                b[i][j] = b[i - 1][(j + 1) % 8];
            else
                b[i][j] = b[i][j - 2] ^ 1;
        }
    }
    // print(a); print(b)
    int ans = 1e9;
    if (n >= 4) {
        int tt = 0;                               //b = long
        for (int k = 0; k < 4; k++) {
            tt = 0;
            for (int i = 0; i < n; i++) {
                for (int j = k; j < m + k; j++) {
                    if ((s[i][j - k] == '0' and b[i][j] == 1) or (s[i][j - k] == '1' and b[i][j] == 0))
                        tt++;
                }
            }
            ans = min(ans, tt);
        }
        tt = 0;
        for (int i = 0; i < nn; i++) {
            for (int j = 0; j < m; j++) {
                b[i][j] ^= 1;
            }
        }

        for (int k = 0; k < 4; k++) {
            tt = 0;
            for (int i = 0; i < n; i++) {
                for (int j = k; j < m + k; j++) {
                    if ((s[i][j - k] == '0' and b[i][j] == 1) or (s[i][j - k] == '1' and b[i][j] == 0))
                        tt++;
                }
            }
            ans = min(ans, tt);
        }
    }
    else {
        // print(a)
        int tt = 0;
        for (int k = 0; k < 4; k++) {
            tt = 0;
            for (int i = k; i < n + k; i++) {
                for (int j = 0; j < m; j++) {
                    if ((s[i - k][j] == '0' and a[i][j] == 1) or (s[i - k][j] == '1' and a[i][j] == 0))
                        tt++;
                }
            }
            ans = min(ans, tt);
            // cout << k << ' ' << ans << '\n';
        }
        tt = 0;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < mm; j++) {
                a[i][j] ^= 1;
            }
        }
        for (int k = 0; k < 4; k++) {
            tt = 0;
            for (int i = k; i < n + k; i++) {
                for (int j = 0; j < m; j++) {
                    if ((s[i - k][j] == '0' and a[i][j] == 1) or (s[i - k][j] == '1' and a[i][j] == 0))
                        tt++;
                }
            }
            ans = min(ans, tt);
        }
    }
    cout << ans;
}


#include<bits/stdc++.h>
using namespace std;

#define all(a) a.begin() , a.end()
#define print(x)   cout<<x<<"\n";
#define pb push_back

template <typename T>
ostream& operator<<(ostream& os, const vector<T>& v) {
    os << "["; for (int i = 0; i < v.size(); ++i) { os << v[i]; if (i != v.size() - 1) os << ", "; } os << "]\n"; return os;
}
template <typename T>
ostream& operator<<(ostream& os, const set<T>& v) {
    os << "["; for (auto it : v) {os << it; if (it != *v.rbegin())os << ", ";} os << "]\n"; return os;
}
template <typename T, typename S>
ostream& operator<<(ostream& os, const map<T, S>& v) {
    for (auto it : v)os << it.first << " : " << it.second << "\n"; return os;
}
template <typename T, typename S>
ostream& operator<<(ostream& os, const pair<T, S>& v) {
    os << "("; os << v.first << ", " << v.second << ")"; return os;
}
void go() {
    cin.tie(nullptr) -> sync_with_stdio(false);
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
}
int32_t main() {
    go();
    int n, m;
    cin >> n >> m;
    if (n >= 4 and m >= 4) {
        cout << -1;
        return 0;
    }
    vector<string> s(n);
    for (int i = 0; i < n; i++) {
        cin >> s[i];
    }
    if (min(n, m) == 1) {
        cout << 0;
        return 0;
    }
    int ans = 1e9;
    if (min(n, m) == 2) {
        int tt = 0;
        if (n == 2) {
            for (int i = 0; i < m; i++) {
                int x = s[0][i] - '0' + s[1][i] - '0';
                if (i % 2 == 0 and x % 2 != 0) {
                    tt++;
                }
            }
            ans = min(ans, tt);
            tt = 0;
            for (int i = 0; i < m; i++) {
                int x = s[0][i] - '0' + s[1][i] - '0';
                if (i % 2 == 0 and x % 2 == 0) {
                    tt++;
                }
            }
            ans = min(ans, tt);
        }
        else {
            tt = 0;
            for (int i = 0; i < n; i++) {
                int x = s[i][0] - '0' + s[i][1] - '0';
                if (i % 2 == 0 and x % 2 == 0) {
                    tt++;
                }
            }
            ans = min(ans, tt);
            tt = 0;
            for (int i = 0; i < n; i++) {
                int x = s[i][0] - '0' + s[i][1] - '0';
                if (i % 2 == 0 and x % 2 != 0) {
                    tt++;
                }
            }
            ans = min(ans, tt);
        }
    }
    else {
        if (n == 3) {
            int tt = 0;
            for (int mask = 0; mask < (1 << 3); mask++) {
                tt = 0;
                int a = (mask >> 2) & 1;
                int b = (mask >> 1) & 1;
                int c = (mask >> 0) & 1;
                int ups = a + b;
                int dwn = b + c;
                for (int i = 0; i < m; i++) {
                    int up   = s[0][i] - '0' + s[1][i] - '0';
                    int down = s[1][i] - '0' + s[2][i] - '0';
                    if (i % 2 == 0) {
                        tt += (ups % 2 != up % 2);
                        tt += (down % 2 != dwn % 2);
                    }
                    else {
                        tt += (ups % 2 == up % 2);
                        tt += (down % 2 == dwn % 2);
                    }
                }
                ans = min(ans, tt);
            }
        }
        else {
            int tt = 0;
            for (int mask = 0; mask < (1 << 3); mask++) {
                tt = 0;
                int a = (mask >> 2) & 1;
                int b = (mask >> 1) & 1;
                int c = (mask >> 0) & 1;
                int ff = a + b;
                int ss = b + c;
                for (int i = 0; i < n; i++) {
                    int lft = s[i][0] - '0' + s[i][1] - '0';
                    int ryt = s[i][1] - '0' + s[i][2] - '0';
                    if (i % 2 == 0) {
                        tt += (ff % 2 == lft % 2);
                        tt += (ss % 2 == ryt % 2);
                    }
                    else {
                        tt += (ff % 2 == lft % 2);
                        tt += (ss % 2 == ryt % 2);
                    }
                }
                ans = min(ans, tt);
            }
        }
    }
    cout << ans;
}


#include<bits/stdc++.h>
using namespace std;

#define all(a) a.begin() , a.end()
#define print(x)   cout<<x<<"\n";
#define pb push_back

template <typename T>
ostream& operator<<(ostream& os, const vector<T>& v) {
    os << "["; for (int i = 0; i < v.size(); ++i) { os << v[i]; if (i != v.size() - 1) os << ", "; } os << "]\n"; return os;
}
template <typename T>
ostream& operator<<(ostream& os, const set<T>& v) {
    os << "["; for (auto it : v) {os << it; if (it != *v.rbegin())os << ", ";} os << "]\n"; return os;
}
template <typename T, typename S>
ostream& operator<<(ostream& os, const map<T, S>& v) {
    for (auto it : v)os << it.first << " : " << it.second << "\n"; return os;
}
template <typename T, typename S>
ostream& operator<<(ostream& os, const pair<T, S>& v) {
    os << "("; os << v.first << ", " << v.second << ")"; return os;
}
void go() {
    cin.tie(nullptr) -> sync_with_stdio(false);
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
}
int32_t main() {
    go();
    int n, m;
    cin >> n >> m;
    if (n >= 4 and m >= 4) {
        cout << -1;
        return 0;
    }
    vector<string> s(n);
    for (int i = 0; i < n; i++) {
        cin >> s[i];
    }
    if (min(n, m) == 1) {
        cout << 0;
        return 0;
    }
    int ans = 1e9;
    if (min(n, m) == 2) {
        int tt = 0;
        if (n == 2) {
            for (int i = 0; i < m; i++) {
                int x = s[0][i] - '0' + s[1][i] - '0';
                if (i % 2 == 0 and x % 2 != 0) {
                    tt++;
                }
            }
            ans = min(ans, tt);
            tt = 0;
            for (int i = 0; i < m; i++) {
                int x = s[0][i] - '0' + s[1][i] - '0';
                if (i % 2 == 0 and x % 2 == 0) {
                    tt++;
                }
            }
            ans = min(ans, tt);
        }
        else {
            tt = 0;
            for (int i = 0; i < n; i++) {
                int x = s[i][0] - '0' + s[i][1] - '0';
                if (i % 2 == 0 and x % 2 == 0) {
                    tt++;
                }
            }
            ans = min(ans, tt);
            tt = 0;
            for (int i = 0; i < n; i++) {
                int x = s[i][0] - '0' + s[i][1] - '0';
                if (i % 2 == 0 and x % 2 != 0) {
                    tt++;
                }
            }
            ans = min(ans, tt);
        }
    }
    else {
        if (n == 3) {
            int tt = 0;
            vector<int> check(1 << 3);
            for (int mask = 0; mask < (1 << 3); mask++) {
                tt = 0;
                int a = (mask >> 2) & 1;
                int b = (mask >> 1) & 1;
                int c = (mask >> 0) & 1;
                int ups = a + b;
                int dwn = b + c;
                for (int i = 0; i < m; i++) {
                    int up   = s[0][i] - '0' + s[1][i] - '0';
                    int down = s[1][i] - '0' + s[2][i] - '0';
                    if (i % 2 == 0) {
                        tt += (ups % 2 != up);
                        tt += (down % 2 != dwn);
                    }
                    else {
                        tt += (ups % 2 == up);
                        tt += (down % 2 == dwn);
                    }
                }
                ans = min(ans, tt);
            }
        }
    }
    cout << ans;
}


#include<bits/stdc++.h>
using namespace std;

#define all(a) a.begin() , a.end()
#define print(x)   cout<<x<<"\n";
#define pb push_back

template <typename T>
ostream& operator<<(ostream& os, const vector<T>& v) {
    os << "["; for (int i = 0; i < v.size(); ++i) { os << v[i]; if (i != v.size() - 1) os << ", "; } os << "]\n"; return os;
}
template <typename T>
ostream& operator<<(ostream& os, const set<T>& v) {
    os << "["; for (auto it : v) {os << it; if (it != *v.rbegin())os << ", ";} os << "]\n"; return os;
}
template <typename T, typename S>
ostream& operator<<(ostream& os, const map<T, S>& v) {
    for (auto it : v)os << it.first << " : " << it.second << "\n"; return os;
}
template <typename T, typename S>
ostream& operator<<(ostream& os, const pair<T, S>& v) {
    os << "("; os << v.first << ", " << v.second << ")"; return os;
}
void go() {
    cin.tie(nullptr) -> sync_with_stdio(false);
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
}
int32_t main() {
    go();
    int n, m;
    cin >> n >> m;
    if (n >= 4 and m >= 4) {
        cout << -1;
        return 0;
    }
    vector<string> s(n);
    for (int i = 0; i < n; i++) {
        cin >> s[i];
    }
    int nn = n + 4;
    int mm = m + 4;
    vector<vector<int>> a(nn, vector<int>(mm, 0));   // a = wide
    a[0][0] = 1;
    a[0][1] = 1;
    for (int i = 2; i < mm; i++) {
        a[0][i] = a[0][i - 2] ^ 1;
    }
    for (int i = 1; i < nn; i++) {
        for (int j = 0; j < mm; j++) {
            if (j < 2) {
                a[i][j] = a[i - 1][(j + 1) % mm];
            }
            else
                a[i][j] = a[i][j - 2] ^ 1;
        }
    }
    // print(a);
    int ans = 1e9;
    if (n >= 4) {
        int tt = 0;                               // b = long
        for (int k = 0; k < 4; k++) {
            tt = 0;
            for (int i = 0; i < n; i++) {
                for (int j = k; j < m + k; j++) {
                    if ((s[i][j - k] == '0' and a[i][j] == 1) or (s[i][j - k] == '1' and a[i][j] == 0))
                        tt++;
                }
            }
            ans = min(ans, tt);
        }
        tt = 0;
        for (int i = 0; i < nn; i++) {
            for (int j = 0; j < mm; j++) {
                a[i][j] ^= 1;
            }
        }

        for (int k = 0; k < 4; k++) {
            tt = 0;
            for (int i = 0; i < n; i++) {
                for (int j = k; j < m + k; j++) {
                    if ((s[i][j - k] == '0' and a[i][j] == 1) or (s[i][j - k] == '1' and a[i][j] == 0))
                        tt++;
                }
            }
            ans = min(ans, tt);
        }
    }
    else {
        // print(a)
        int tt = 0;
        for (int k = 0; k < 4; k++) {
            tt = 0;
            for (int i = k; i < n + k; i++) {
                for (int j = 0; j < m; j++) {
                    if ((s[i - k][j] == '0' and a[i][j] == 1) or (s[i - k][j] == '1' and a[i][j] == 0))
                        tt++;
                }
            }
            ans = min(ans, tt);
            // cout << k << ' ' << ans << '\n';
        }
        tt = 0;
        for (int i = 0; i < nn; i++) {
            for (int j = 0; j < mm; j++) {
                a[i][j] ^= 1;
            }
        }
        for (int k = 0; k < 4; k++) {
            tt = 0;
            for (int i = k; i < n + k; i++) {
                for (int j = 0; j < m; j++) {
                    if ((s[i - k][j] == '0' and a[i][j] == 1) or (s[i - k][j] == '1' and a[i][j] == 0))
                        tt++;
                }
            }
            ans = min(ans, tt);
        }
    }
    cout << ans;
}


#include<bits/stdc++.h>
using namespace std;

#define all(a) a.begin() , a.end()
#define print(x)   cout<<x<<"\n";
#define pb push_back

template <typename T>
ostream& operator<<(ostream& os, const vector<T>& v) {
    os << "["; for (int i = 0; i < v.size(); ++i) { os << v[i]; if (i != v.size() - 1) os << ", "; } os << "]\n"; return os;
}
template <typename T>
ostream& operator<<(ostream& os, const set<T>& v) {
    os << "["; for (auto it : v) {os << it; if (it != *v.rbegin())os << ", ";} os << "]\n"; return os;
}
template <typename T, typename S>
ostream& operator<<(ostream& os, const map<T, S>& v) {
    for (auto it : v)os << it.first << " : " << it.second << "\n"; return os;
}
template <typename T, typename S>
ostream& operator<<(ostream& os, const pair<T, S>& v) {
    os << "("; os << v.first << ", " << v.second << ")"; return os;
}
void go() {
    cin.tie(nullptr) -> sync_with_stdio(false);
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
}
int32_t main() {
    go();
    int n, m;
    cin >> n >> m;
    if (n >= 4 and m >= 4) {
        cout << -1;
        return 0;
    }
    vector<string> s(n);
    for (int i = 0; i < n; i++) {
        cin >> s[i];
    }
    if (min(n, m) == 1) {
        cout << 0;
        return 0;
    }
    int ans = 1e9;
    if (min(n, m) == 2) {
        int tt = 0;
        if (n == 2) {
            for (int i = 0; i < m; i++) {
                int x = s[0][i] - '0' + s[1][i] - '0';
                if (i % 2 == 0 and x % 2 != 0) {
                    tt++;
                }
            }
            ans = min(ans, tt);
            tt = 0;
            for (int i = 0; i < m; i++) {
                int x = s[0][i] - '0' + s[1][i] - '0';
                if (i % 2 == 0 and x % 2 == 0) {
                    tt++;
                }
            }
            ans = min(ans, tt);
        }
        else {
            tt = 0;
            for (int i = 0; i < n; i++) {
                int x = s[i][0] - '0' + s[i][1] - '0';
                if (i % 2 == 0 and x % 2 == 0) {
                    tt++;
                }
            }
            ans = min(ans, tt);
            tt = 0;
            for (int i = 0; i < n; i++) {
                int x = s[i][0] - '0' + s[i][1] - '0';
                if (i % 2 == 0 and x % 2 != 0) {
                    tt++;
                }
            }
            ans = min(ans, tt);
        }
    }
    else {
        if (n == 3) {
            int tt = 0;
            for (int mask = 0; mask < (1 << 2); mask++) {
                tt = 0;

                // int a = ((mask >> 2) & 1);
                // int b = ((mask >> 1) & 1);
                // int c = ((mask >> 0) & 1);
                // int ups = a + b;
                // int dwn = b + c;

                int ups = (mask & 1);
                int dwn = ((mask >> 1) & 1);
                for (int i = 0; i < m; i++) {
                    int up   = s[0][i] - '0' + s[1][i] - '0';
                    int down = s[1][i] - '0' + s[2][i] - '0';
                    if (i % 2 == 0) {
                        tt += (ups  != (up % 2));
                        tt += (dwn != (down % 2));
                    }
                    else {
                        tt += ((up % 2)  == ups);
                        tt += ((down % 2) == dwn);
                    }
                }
                ans = min(ans, tt);
            }
        }
        else {
            int tt = 0;
            for (int mask = 0; mask < (1 << 3); mask++) {
                tt = 0;
                int a = ((mask >> 2) & 1);
                int b = ((mask >> 1) & 1);
                int c = ((mask >> 0) & 1);
                int ff = a + b;
                int ss = b + c;
                for (int i = 0; i < n; i++) {
                    int lft = s[i][0] - '0' + s[i][1] - '0';
                    int ryt = s[i][1] - '0' + s[i][2] - '0';
                    if (i % 2 == 0) {
                        tt += (ff % 2 == lft % 2);
                        tt += (ss % 2 == ryt % 2);
                    }
                    else {
                        tt += (ff % 2 != lft % 2);
                        tt += (ss % 2 != ryt % 2);
                    }
                }
                ans = min(ans, tt);
            }
        }
    }
    cout << ans;
}


#include<bits/stdc++.h>
using namespace std;

#define all(a) a.begin() , a.end()
#define print(x)   cout<<x<<"\n";
#define pb push_back

template <typename T>
ostream& operator<<(ostream& os, const vector<T>& v) {
    os << "["; for (int i = 0; i < v.size(); ++i) { os << v[i]; if (i != v.size() - 1) os << ", "; } os << "]\n"; return os;
}
template <typename T>
ostream& operator<<(ostream& os, const set<T>& v) {
    os << "["; for (auto it : v) {os << it; if (it != *v.rbegin())os << ", ";} os << "]\n"; return os;
}
template <typename T, typename S>
ostream& operator<<(ostream& os, const map<T, S>& v) {
    for (auto it : v)os << it.first << " : " << it.second << "\n"; return os;
}
template <typename T, typename S>
ostream& operator<<(ostream& os, const pair<T, S>& v) {
    os << "("; os << v.first << ", " << v.second << ")"; return os;
}
void go() {
    cin.tie(nullptr) -> sync_with_stdio(false);
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
}
int32_t main() {
    go();
    int n, m;
    cin >> n >> m;
    if (n >= 4 and m >= 4) {
        cout << -1;
        return 0;
    }
    vector<string> s(n);
    for (int i = 0; i < n; i++) {
        cin >> s[i];
    }
    int nn = n + 4;
    int mm = m + 4;
    vector<vector<int>> a(nn, vector<int>(mm, 0));   // a = wide
    a[0][0] = 1;
    a[0][1] = 1;
    for (int i = 2; i < mm; i++) {
        a[0][i] = a[0][i - 2] ^ 1;
    }
    for (int i = 1; i < nn; i++) {
        for (int j = 0; j < mm; j++) {
            if (j < 2) {
                a[i][j] = a[i - 1][(j + 1) % mm];
            }
            else
                a[i][j] = a[i][j - 2] ^ 1;
        }
    }
    // print(a);
    int ans = 1e9;
    int tt = 0;
    for (int kk = 0; kk < 4; kk++) {
        for (int k = 0; k < 4; k++) {
            tt = 0;
            for (int i = kk; i < n + kk; i++) {
                for (int j = k; j < m + k; j++) {
                    if ((s[i - kk][j - k] == '0' and a[i][j] == 1) or (s[i - kk][j - k] == '1' and a[i][j] == 0))
                        tt++;
                }
            }
            ans = min(ans, tt);
        }
    }
    tt = 0;
    for (int i = 0; i < nn; i++) {
        for (int j = 0; j < mm; j++) {
            a[i][j] ^= 1;
        }
    }
    for (int kk = 0; kk < 4; kk++) {
        for (int k = 0; k < 4; k++) {
            tt = 0;
            for (int i = kk; i < n + kk; i++) {
                for (int j = k; j < m + k; j++) {
                    if ((s[i - kk][j - k] == '0' and a[i][j] == 1) or (s[i - kk][j - k] == '1' and a[i][j] == 0))
                        tt++;
                }
            }
            ans = min(ans, tt);
        }
    }
    cout << ans;
}


#include<bits/stdc++.h>
using namespace std;

#define all(a) a.begin() , a.end()
#define print(x)   cout<<x<<"\n";
#define pb push_back

template <typename T>
ostream& operator<<(ostream& os, const vector<T>& v) {
    os << "["; for (int i = 0; i < v.size(); ++i) { os << v[i]; if (i != v.size() - 1) os << ", "; } os << "]\n"; return os;
}
template <typename T>
ostream& operator<<(ostream& os, const set<T>& v) {
    os << "["; for (auto it : v) {os << it; if (it != *v.rbegin())os << ", ";} os << "]\n"; return os;
}
template <typename T, typename S>
ostream& operator<<(ostream& os, const map<T, S>& v) {
    for (auto it : v)os << it.first << " : " << it.second << "\n"; return os;
}
template <typename T, typename S>
ostream& operator<<(ostream& os, const pair<T, S>& v) {
    os << "("; os << v.first << ", " << v.second << ")"; return os;
}
void go() {
    cin.tie(nullptr) -> sync_with_stdio(false);
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
}
int32_t main() {
    go();
    int n, m;
    cin >> n >> m;
    if (n >= 4 and m >= 4) {
        cout << -1;
        return 0;
    }
    vector<string> s(n);
    for (int i = 0; i < n; i++) {
        cin >> s[i];
    }
    if (min(n, m) == 1) {
        cout << 0;
        return 0;
    }
    int ans = 1e9;
    if (min(n, m) == 2) {
        int tt = 0;
        if (n == 2) {
            for (int i = 0; i < m; i++) {
                int x = s[0][i] - '0' + s[1][i] - '0';
                if (i % 2 == 0 and x % 2 != 0) {
                    tt++;
                }
                else if (i % 2 != 0 and x % 2 == 0) {
                    tt++;
                }
            }
            ans = min(ans, tt);
            tt = 0;
            for (int i = 0; i < m; i++) {
                int x = s[0][i] - '0' + s[1][i] - '0';
                if (i % 2 == 0 and x % 2 == 0) {
                    tt++;
                }
                else if (i % 2 == 1 and x % 2 == 1) {
                    tt++;
                }
            }
            ans = min(ans, tt);
        }
        else {
            tt = 0;
            for (int i = 0; i < n; i++) {
                int x = s[i][0] - '0' + s[i][1] - '0';
                if (i % 2 == 0 and x % 2 != 0) {
                    tt++;
                }
                else if (i % 2 != 0 and x % 2 == 0) {
                    tt++;
                }
            }
            ans = min(ans, tt);
            tt = 0;
            for (int i = 0; i < n; i++) {
                int x = s[i][0] - '0' + s[i][1] - '0';
                if (i % 2 == 0 and x % 2 == 0) {
                    tt++;
                }
                else if (i % 2 == 1 and x % 2 == 1) {
                    tt++;
                }
            }
            ans = min(ans, tt);
        }
    }
    else {
        if (n == 3) {
            int tt = 0;
            for (int mask = 0; mask < (1 << 2); mask++) {
                tt = 0;

                // int a = ((mask >> 2) & 1);
                // int b = ((mask >> 1) & 1);
                // int c = ((mask >> 0) & 1);
                // int ups = a + b;
                // int dwn = b + c;

                int ups = (mask & 1);
                int dwn = ((mask >> 1) & 1);
                // cout << ups << ' ' << dwn << '\n';
                for (int i = 0; i < m; i++) {
                    int up   = s[0][i] - '0' + s[1][i] - '0';
                    int down = s[1][i] - '0' + s[2][i] - '0';
                    int pp = 0;
                    if (i % 2 == 0) {
                        pp += (ups  != (up % 2));
                        pp += (dwn != (down % 2));
                    }
                    else {
                        pp += ((up % 2)  == ups);
                        pp += ((down % 2) == dwn);
                    }
                    if (pp == 2)
                        --pp;
                    tt += pp;
                }
                ans = min(ans, tt);
            }
        }
        else {
            int tt = 0;
            for (int mask = 0; mask < (1 << 2); mask++) {
                int ff = (mask & 1);
                int ss = ((mask >> 1) & 1);
                for (int i = 0; i < n; i++) {
                    int lft = s[i][0] - '0' + s[i][1] - '0';
                    int ryt = s[i][1] - '0' + s[i][2] - '0';
                    int pp = 0;
                    if (i % 2 == 0) {
                        pp += (ff == lft % 2);
                        pp += (ss == ryt % 2);
                    }
                    else {
                        pp += (ff != lft % 2);
                        pp += (ss != ryt % 2);
                    }
                    if (pp == 2)
                        --pp;
                    tt += pp;
                }
                ans = min(ans, tt);
            }
        }
    }
    cout << ans;
}


#include<bits/stdc++.h>
using namespace std;

#define all(a) a.begin() , a.end()
#define print(x)   cout<<x<<"\n";
#define pb push_back

template <typename T>
ostream& operator<<(ostream& os, const vector<T>& v) {
    os << "["; for (int i = 0; i < v.size(); ++i) { os << v[i]; if (i != v.size() - 1) os << ", "; } os << "]\n"; return os;
}
template <typename T>
ostream& operator<<(ostream& os, const set<T>& v) {
    os << "["; for (auto it : v) {os << it; if (it != *v.rbegin())os << ", ";} os << "]\n"; return os;
}
template <typename T, typename S>
ostream& operator<<(ostream& os, const map<T, S>& v) {
    for (auto it : v)os << it.first << " : " << it.second << "\n"; return os;
}
template <typename T, typename S>
ostream& operator<<(ostream& os, const pair<T, S>& v) {
    os << "("; os << v.first << ", " << v.second << ")"; return os;
}
void go() {
    cin.tie(nullptr) -> sync_with_stdio(false);
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
}
int32_t main() {
    go();
    int n, m;
    cin >> n >> m;
    if (n >= 4 and m >= 4) {
        cout << -1;
        return 0;
    }
    vector<string> s(n);
    for (int i = 0; i < n; i++) {
        cin >> s[i];
    }
    int nn = max(n, 4);
    int mm = max(m, 4);
    vector<vector<int>> a(8, vector<int>(mm, 0));   //a=wide
    vector<vector<int>> b(nn, vector<int>(8, 0));
    a[0][0] = 1;
    a[0][1] = 1;
    b[0][0] = 1;
    b[0][1] = 1;
    for (int i = 2; i < mm; i++) {
        a[0][i] = a[0][i - 2] ^ 1;
    }
    for (int i = 2; i < 8; i++) {
        b[0][i] = b[0][i - 2] ^ 1;
    }
    for (int i = 1; i < 8; i++) {
        for (int j = 0; j < mm; j++) {
            if (j < 2) {
                a[i][j] = a[i - 1][(j + 1) % mm];
            }
            else
                a[i][j] = a[i][j - 2] ^ 1;
        }
    }
    for (int i = 1; i < nn; i++) {
        for (int j = 0; j < 8; j++) {
            if (j < 2)
                b[i][j] = b[i - 1][(j + 1) % 8];
            else
                b[i][j] = b[i][j - 2] ^ 1;
        }
    }
    // print(a); print(b)
    int ans = 1e9;
    if (n >= 4) {
        int tt = 0;                               //b = long
        for (int k = 0; k < 4; k++) {
            tt = 0;
            for (int i = 0; i < n; i++) {
                for (int j = k; j < m + k; j++) {
                    if ((s[i][j - k] == '0' and b[i][j] == 1) or (s[i][j - k] == '1' and b[i][j] == 0))
                        tt++;
                }
            }
            ans = min(ans, tt);
        }
        tt = 0;
        for (int i = 0; i < nn; i++) {
            for (int j = 0; j < m; j++) {
                b[i][j] ^= 1;
            }
        }

        for (int k = 0; k < 4; k++) {
            tt = 0;
            for (int i = 0; i < n; i++) {
                for (int j = k; j < m + k; j++) {
                    if ((s[i][j - k] == '0' and b[i][j] == 1) or (s[i][j - k] == '1' and b[i][j] == 0))
                        tt++;
                }
            }
            ans = min(ans, tt);
        }
    }
    else {
        // print(a)
        int tt = 0;
        for (int k = 0; k < 4; k++) {
            tt = 0;
            for (int i = k; i < n + k; i++) {
                for (int j = 0; j < m; j++) {
                    if ((s[i - k][j] == '0' and a[i][j] == 1) or (s[i - k][j] == '1' and a[i][j] == 0))
                        tt++;
                }
            }
            ans = min(ans, tt);
            // cout << k << ' ' << ans << '\n';
        }
        tt = 0;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < mm; j++) {
                a[i][j] ^= 1;
            }
        }
        for (int k = 0; k < 4; k++) {
            tt = 0;
            for (int i = k; i < n + k; i++) {
                for (int j = 0; j < m; j++) {
                    if ((s[i - k][j] == '0' and a[i][j] == 1) or (s[i - k][j] == '1' and a[i][j] == 0))
                        tt++;
                }
            }
            ans = min(ans, tt);
        }
    }
    cout << ans;
}