#include "bits/stdc++.h"
using namespace std;
typedef int ll;
typedef pair<ll ,ll> pll;
#define F first
#define S second
#define pb push_back
#define mp make_pair
#define all(X) (X).begin(), (X).end()
#define REP(i,x,y) for(ll i = x;i <= y;++i)
#define fastio ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0)
vector<string> vec_splitter(string s) {
    for(char& c: s) c = c == ','?  ' ': c;
    stringstream ss; ss << s;
    vector<string> res;
    for(string z; ss >> z; res.push_back(z))
        ;
    return res;
}
void debug_out(vector<string> args, int idx) { cerr << endl; }
template <typename Head, typename... Tail>
void debug_out(vector<string> args, int idx, Head H, Tail... T) {
    if(idx > 0) cerr << ", ";
    stringstream ss; ss << H;
    cerr << args[idx] << " = " << ss.str();
    debug_out(args, idx + 1, T...);
}
#define debug(...) debug_out(vec_splitter(#__VA_ARGS__), 0, __VA_ARGS__)
void localTest() {
    #ifndef ONLINE_JUDGE
        freopen("inp", "r", stdin);
        freopen("out", "w", stdout);
    #endif
}
const ll N = 1e6 + 5, inf = 1e9;
ll dp[N][8], n, m, msk[N], bit[1000];
vector<ll> submask[10];
vector<vector<ll>> A;
ll doit(ll idx, ll mask) {
	if(idx > m) return 0;
	ll &ret = dp[idx][mask];
	if(ret != -1) return ret;
	ll curr = msk[idx];
	vector<vector<ll>> aux(n, vector<ll>(2, 0));
	for(ll i = 0; i < n; ++i) {
		if(mask & (1LL << i)) aux[i][0] = 1;
	}
	ll ans = inf;
	for(ll sm = 0; sm < (1LL << n); ++sm) {
		for(ll i = 0; i < n; ++i) {
			if(sm & (1LL << i)) aux[i][1] = 1;
			else {
				aux[i][1] = 0;
			}
		}
		ll c1 = aux[0][0] + aux[0][1] + aux[1][0] + aux[1][1];
		if(c1 % 2 == 0) continue;
		if(n > 2) {
			c1 = aux[1][0] + aux[1][1] + aux[2][0] + aux[2][1];
			if(c1 % 2 == 0) continue;
		}
		ans = min(ans, bit[sm ^ curr] + doit(idx + 1, sm));
	}
	return ret = ans;
}
int main() {

    localTest();
    fastio;
    for(int i = 0; i < 10; ++i) {
    	for(int j = 0; j < 10; ++j) {
    		bit[i ^ j] = __builtin_popcount(i ^ j);
    	}
    }
 	cin >> n >> m;
 	A.resize(n + 1);
 	for(ll i = 1; i <= n; ++i) {
 		string s;
 		cin >> s;
 		A[i].resize(m + 1, 0);
 		for(ll j = 1; j <= m; ++j) {
 			if(s[j - 1] == '1') A[i][j] = 1;
 		}
 	}
 	if(n >= 4 && m >= 4) {
 		cout << "-1\n";
 	}
 	else if(n == 1 || m == 1) cout << "0\n";
 	else {
 		// memset(dp, -1, sizeof dp);
 		// debug(n);
 		if(n > m) {
 			vector<vector<ll>> B = A;
 			for(ll j = 1; j <= m; ++j) {
 				for(ll i = 1; i <= n; ++i) {
 					B[j][i] = A[i][j];
 				}
 			}
 			swap(n, m);
 			A = B;
 		}
 		for(ll i = 1; i <= m; ++i) {
 			ll cur = 0;
	 		for(ll j = 1; j <= n; ++j) {
				if(A[j][i]) cur |= (1LL << (j - 1));
			}
			msk[i] = cur;
		}
 		for(ll i = 1; i <= m; ++i) {
 			for(ll j = 0;j < 8; ++j) dp[i][j] = -1;
 		}
 		ll mask = msk[1];
		ll val = inf;
		// debug(m);
		assert(n <= 3);
		for(ll sm = 0; sm < (1LL << n); ++sm) val = min(val, bit[sm ^ mask] + doit(2, sm));
		if(val >= inf) val = -1;
		cout << val << "\n";
 	}

    return 0;
}


#include "bits/stdc++.h"
using namespace std;
typedef long long ll;
typedef pair<ll ,ll> pll;
#define F first
#define S second
#define pb push_back
#define mp make_pair
#define all(X) (X).begin(), (X).end()
#define REP(i,x,y) for(ll i = x;i <= y;++i)
#define fastio ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0)
vector<string> vec_splitter(string s) {
    for(char& c: s) c = c == ','?  ' ': c;
    stringstream ss; ss << s;
    vector<string> res;
    for(string z; ss >> z; res.push_back(z))
        ;
    return res;
}
void debug_out(vector<string> args, int idx) { cerr << endl; }
template <typename Head, typename... Tail>
void debug_out(vector<string> args, int idx, Head H, Tail... T) {
    if(idx > 0) cerr << ", ";
    stringstream ss; ss << H;
    cerr << args[idx] << " = " << ss.str();
    debug_out(args, idx + 1, T...);
}
#define debug(...) debug_out(vec_splitter(#__VA_ARGS__), 0, __VA_ARGS__)
void localTest() {
    #ifndef ONLINE_JUDGE
        freopen("inp", "r", stdin);
        freopen("out", "w", stdout);
    #endif
}
const ll N = 1e6 + 5, inf = 1e9;
ll dp[N][8], n, m;
vector<ll> submask[10];
vector<vector<ll>> A;
ll doit(ll idx, ll mask) {
	if(idx > m) return 0;
	ll &ret = dp[idx][mask];
	if(ret != -1) return ret;
	ll curr = 0;
	for(ll j = 1; j <= n; ++j) {
		if(A[j][idx]) curr |= (1LL << (j - 1));
	}
	vector<vector<ll>> aux(n, vector<ll>(2, 0));
	for(ll i = 0; i < n; ++i) {
		if(mask & (1LL << i)) aux[i][0] = 1;
	}
	ll ans = inf;
	for(ll sm = 0; sm < (1LL << n); ++sm) {
		for(ll i = 0; i < n; ++i) {
			if(sm & (1LL << i)) aux[i][1] = 1;
			else {
				aux[i][1] = 0;
			}
		}
		ll c1 = aux[0][0] + aux[0][1] + aux[1][0] + aux[1][1];
		if(c1 % 2 == 0) continue;
		if(n > 2) {
			c1 = aux[1][0] + aux[1][1] + aux[2][0] + aux[2][1];
			if(c1 % 2 == 0) continue;
		}
		ans = min(ans, __builtin_popcount(sm ^ curr) + doit(idx + 1, sm));
	}
	return ret = ans;
}
int main() {

    localTest();
    fastio;
 	cin >> n >> m;
 	A.resize(n + 1);
 	for(ll i = 1; i <= n; ++i) {
 		string s;
 		cin >> s;
 		A[i].resize(m + 1, 0);
 		for(ll j = 1; j <= m; ++j) {
 			if(s[j - 1] == '1') A[i][j] = 1;
 		}
 	}
 	if(n >= 4 && m >= 4) {
 		cout << "-1\n";
 	}
 	else if(n == 1 || m == 1) cout << "0\n";
 	else {
 		// memset(dp, -1, sizeof dp);
 		if(n > m) {
 			vector<vector<ll>> B = A;
 			for(ll j = 1; j <= m; ++j) {
 				for(ll i = 1; i <= n; ++i) {
 					B[j][i] = A[i][j];
 				}
 			}
 			swap(n, m);
 			A = B;
 		}
 		for(ll i = 1; i <= m; ++i) {
 			for(ll j = 0;j < 8; ++j) dp[i][j] = -1;
 		}
 		ll mask = 0;
		for(ll j = 1; j <= n; ++j) {
			if(A[j][1]) mask |= (1LL << (j - 1));
		}
		ll val = inf;
		for(ll sm = 0; sm < (1LL << n); ++sm) val = min(val, __builtin_popcount(sm ^ mask) + doit(2, sm));
		if(val >= inf) val = -1;
		cout << val << "\n";
 	}

    return 0;
}


#include "bits/stdc++.h"
using namespace std;
typedef long long ll;
typedef pair<ll ,ll> pll;
#define F first
#define S second
#define pb push_back
#define mp make_pair
#define all(X) (X).begin(), (X).end()
#define REP(i,x,y) for(ll i = x;i <= y;++i)
#define fastio ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0)
vector<string> vec_splitter(string s) {
    for(char& c: s) c = c == ','?  ' ': c;
    stringstream ss; ss << s;
    vector<string> res;
    for(string z; ss >> z; res.push_back(z))
        ;
    return res;
}
void debug_out(vector<string> args, int idx) { cerr << endl; }
template <typename Head, typename... Tail>
void debug_out(vector<string> args, int idx, Head H, Tail... T) {
    if(idx > 0) cerr << ", ";
    stringstream ss; ss << H;
    cerr << args[idx] << " = " << ss.str();
    debug_out(args, idx + 1, T...);
}
#define debug(...) debug_out(vec_splitter(#__VA_ARGS__), 0, __VA_ARGS__)
void localTest() {
    #ifndef ONLINE_JUDGE
        freopen("inp", "r", stdin);
        freopen("out", "w", stdout);
    #endif
}
const ll N = 1e6 + 5, inf = 1e16;
ll dp[N][10];
vector<ll> submask[10];
ll doit(vector<vector<ll>> &A, ll idx, ll mask, ll n, ll m, ll fl) {
	if(idx > n) return 0;
	ll &ret = dp[idx][mask];
	if(ret != -1) return ret;
	ll curr = 0;
	for(ll j = 1; j <= m; ++j) {
		if(fl) {
			if(A[idx][j]) curr |= (1LL << (j - 1));
		}
		else {
			if(A[j][idx]) curr |= (1LL << (j - 1));
		}
	}
	vector<vector<ll>> aux(m, vector<ll>(2, 0));
	for(ll i = 0; i < 3; ++i) {
		if(mask & (1LL << i)) aux[i][0] = 1;
		else aux[i][0] = 0;
	}
	ll ans = inf;
	for(auto sm : submask[curr]) {
		// debug(idx, mask, sm);
		for(ll i = 0; i < 3; ++i) {
			if(sm & (1LL << i)) aux[i][1] = 1;
			else aux[i][1] = 0;
		}
		// for(ll i = 0; i < m; ++i) {
		// 	for(ll j = 0; j < 2; ++j) debug(i, j, aux[i][j], sm, idx, mask, curr);
		// }
		ll c1 = aux[0][0] + aux[0][1] + aux[1][0] + aux[1][1];
		if(c1 % 2 == 0) continue;
		if(m > 2) {
			c1 = aux[1][0] + aux[1][1] + aux[2][0] + aux[2][1];
			if(c1 % 2 == 0) continue;
		}
		// debug("haha");
		ans = min(ans, __builtin_popcount(sm ^ curr) + doit(A, idx + 1, sm, n, m, fl));
	}
	return ret = ans;
}
int main() {

    localTest();
    fastio;
    for(ll i = 0; i < 10; ++i) {
    	submask[i].pb(0);
    	for(ll j = i; j > 0; j = (i & (j - 1))) submask[i].pb(j);
    }
 	ll n, m;
 	cin >> n >> m;
 	vector<vector<ll>> A(n + 1, vector<ll>(m + 1, 0));
 	for(ll i = 1; i <= n; ++i) {
 		string s;
 		cin >> s;
 		for(ll j = 1; j <= m; ++j) {
 			if(s[j - 1] == '1') A[i][j] = 1;
 		}
 	}
 	if(n >= 4 && m >= 4) {
 		cout << "-1\n";
 	}
 	else if(n == 1 || m == 1) cout << "0\n";
 	else {
 		memset(dp, -1, sizeof dp);
 		if(n > m) {
 			vector<vector<ll>> B;
 			vector<ll> ele(n, 0);
 			B.pb(ele);
 			for(ll j = 1; j <= m; ++j) {
 				vector<ll> aux;
 				aux.pb(0);
 				for(ll i = 1; i <= n; ++i) {
 					aux.pb(A[i][j]);
 				}
 				B.pb(aux);
 			}
 			swap(n, m);
 			A = B;
 		}
 		// for(ll i = 1; i <= n; ++i) {
 		// 	for(ll j = 1; j <= m; ++j) cout << A[i][j];
 		// 	cout << "\n";
 		// }
 		// if(n > m) {
 		// 	ll mask = 0;
 		// 	for(ll j = 1; j <= m; ++j) {
 		// 		if(A[1][j]) mask |= (1LL << (j - 1));
 		// 	}
 		// 	ll val = doit(A, 2, mask, n, m, 1);
 		// 	for(auto sm : submask[mask]) val = min(val, __builtin_popcount(sm ^ mask) + doit(A, 2, sm, n, m, 1));
 		// 	if(val >= inf) val = -1;
 		// 	cout << val << "\n";
 		// } else {
		ll mask = 0;
		for(ll j = 1; j <= n; ++j) {
			if(A[j][1]) mask |= (1LL << (j - 1));
		}
		// debug(mask);
		ll val = inf;
		for(auto sm : submask[mask]) val = min(val, __builtin_popcount(sm ^ mask) + doit(A, 2, sm, m, n, 0));
		if(val >= inf) val = -1;
		cout << val << "\n";
 		// }
 	}

    return 0;
}


#include "bits/stdc++.h"
using namespace std;
typedef long long ll;
typedef pair<ll ,ll> pll;
#define F first
#define S second
#define pb push_back
#define mp make_pair
#define all(X) (X).begin(), (X).end()
#define REP(i,x,y) for(ll i = x;i <= y;++i)
#define fastio ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0)
vector<string> vec_splitter(string s) {
    for(char& c: s) c = c == ','?  ' ': c;
    stringstream ss; ss << s;
    vector<string> res;
    for(string z; ss >> z; res.push_back(z))
        ;
    return res;
}
void debug_out(vector<string> args, int idx) { cerr << endl; }
template <typename Head, typename... Tail>
void debug_out(vector<string> args, int idx, Head H, Tail... T) {
    if(idx > 0) cerr << ", ";
    stringstream ss; ss << H;
    cerr << args[idx] << " = " << ss.str();
    debug_out(args, idx + 1, T...);
}
#define debug(...) debug_out(vec_splitter(#__VA_ARGS__), 0, __VA_ARGS__)
void localTest() {
    #ifndef ONLINE_JUDGE
        freopen("inp", "r", stdin);
        freopen("out", "w", stdout);
    #endif
}
const ll N = 1e6 + 5, inf = 1e9;
ll dp[N][10];
vector<ll> submask[10];
ll doit(vector<vector<ll>> &A, ll idx, ll mask, ll n, ll m, ll fl) {
	if(idx > n) return 0;
	ll &ret = dp[idx][mask];
	if(ret != -1) return ret;
	ll curr = 0;
	for(ll j = 1; j <= m; ++j) {
		if(A[j][idx]) curr |= (1LL << (j - 1));
	}
	vector<vector<ll>> aux(m, vector<ll>(2, 0));
	for(ll i = 0; i < m; ++i) {
		if(mask & (1LL << i)) aux[i][0] = 1;
	}
	ll ans = inf;
	for(ll sm = 0; sm < (1LL << m); ++sm) {
		for(ll i = 0; i < m; ++i) {
			if(sm & (1LL << i)) aux[i][1] = 1;
			else {
				aux[i][1] = 0;
			}
		}
		ll c1 = aux[0][0] + aux[0][1] + aux[1][0] + aux[1][1];
		if(c1 % 2 == 0) continue;
		if(m > 2) {
			c1 = aux[1][0] + aux[1][1] + aux[2][0] + aux[2][1];
			if(c1 % 2 == 0) continue;
		}
		ans = min(ans, __builtin_popcount(sm ^ curr) + doit(A, idx + 1, sm, n, m, fl));
	}
	return ret = ans;
}
int main() {

    localTest();
    fastio;
    for(ll i = 0; i < 10; ++i) {
    	submask[i].pb(0);
    	for(ll j = i; j > 0; j = (i & (j - 1))) submask[i].pb(j);
    }
 	ll n, m;
 	cin >> n >> m;
 	vector<vector<ll>> A(n + 1, vector<ll>(m + 1, 0));
 	for(ll i = 1; i <= n; ++i) {
 		string s;
 		cin >> s;
 		for(ll j = 1; j <= m; ++j) {
 			if(s[j - 1] == '1') A[i][j] = 1;
 		}
 	}
 	if(n >= 4 && m >= 4) {
 		cout << "-1\n";
 	}
 	else if(n == 1 || m == 1) cout << "0\n";
 	else {
 		memset(dp, -1, sizeof dp);
 		if(n > m) {
 			vector<vector<ll>> B = A;
 			for(ll j = 1; j <= m; ++j) {
 				for(ll i = 1; i <= n; ++i) {
 					B[j][i] = A[i][j];
 					// debug(j, i, B[i][j]);
 				}
 			}
 			// debug(B.size(), B[0].size());
 			swap(n, m);
 			A = B;
 		}
 		ll mask = 0;
		for(ll j = 1; j <= n; ++j) {
			if(A[j][1]) mask |= (1LL << (j - 1));
		}
		ll val = inf;
		for(ll sm = 0; sm < (1LL << n); ++sm) val = min(val, __builtin_popcount(sm ^ mask) + doit(A, 2, sm, m, n, 0));
		if(val >= inf) val = -1;
		cout << val << "\n";
 	}

    return 0;
}


#include "bits/stdc++.h"
using namespace std;
typedef long long ll;
typedef pair<ll ,ll> pll;
#define F first
#define S second
#define pb push_back
#define mp make_pair
#define all(X) (X).begin(), (X).end()
#define REP(i,x,y) for(ll i = x;i <= y;++i)
#define fastio ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0)
vector<string> vec_splitter(string s) {
    for(char& c: s) c = c == ','?  ' ': c;
    stringstream ss; ss << s;
    vector<string> res;
    for(string z; ss >> z; res.push_back(z))
        ;
    return res;
}
void debug_out(vector<string> args, int idx) { cerr << endl; }
template <typename Head, typename... Tail>
void debug_out(vector<string> args, int idx, Head H, Tail... T) {
    if(idx > 0) cerr << ", ";
    stringstream ss; ss << H;
    cerr << args[idx] << " = " << ss.str();
    debug_out(args, idx + 1, T...);
}
#define debug(...) debug_out(vec_splitter(#__VA_ARGS__), 0, __VA_ARGS__)
void localTest() {
    #ifndef ONLINE_JUDGE
        freopen("inp", "r", stdin);
        freopen("out", "w", stdout);
    #endif
}
const ll N = 1e6 + 5, inf = 1e9;
ll dp[N][8];
vector<ll> submask[10];
ll doit(vector<vector<ll>> &A, ll idx, ll mask, ll n, ll m, ll fl) {
	if(idx > n) return 0;
	ll &ret = dp[idx][mask];
	if(ret != -1) return ret;
	ll curr = 0;
	for(ll j = 1; j <= m; ++j) {
		if(A[j][idx]) curr |= (1LL << (j - 1));
	}
	vector<vector<ll>> aux(m, vector<ll>(2, 0));
	for(ll i = 0; i < m; ++i) {
		if(mask & (1LL << i)) aux[i][0] = 1;
	}
	ll ans = inf;
	for(ll sm = 0; sm < (1LL << m); ++sm) {
		for(ll i = 0; i < m; ++i) {
			if(sm & (1LL << i)) aux[i][1] = 1;
			else {
				aux[i][1] = 0;
			}
		}
		ll c1 = aux[0][0] + aux[0][1] + aux[1][0] + aux[1][1];
		if(c1 % 2 == 0) continue;
		if(m > 2) {
			c1 = aux[1][0] + aux[1][1] + aux[2][0] + aux[2][1];
			if(c1 % 2 == 0) continue;
		}
		ans = min(ans, __builtin_popcount(sm ^ curr) + doit(A, idx + 1, sm, n, m, fl));
	}
	return ret = ans;
}
int main() {

    localTest();
    fastio;
 	ll n, m;
 	cin >> n >> m;
 	vector<vector<ll>> A(n + 1, vector<ll>(m + 1, 0));
 	for(ll i = 1; i <= n; ++i) {
 		string s;
 		cin >> s;
 		for(ll j = 1; j <= m; ++j) {
 			if(s[j - 1] == '1') A[i][j] = 1;
 		}
 	}
 	if(n >= 4 && m >= 4) {
 		cout << "-1\n";
 	}
 	else if(n == 1 || m == 1) cout << "0\n";
 	else {
 		memset(dp, -1, sizeof dp);
 		if(n > m) {
 			vector<vector<ll>> B = A;
 			for(ll j = 1; j <= m; ++j) {
 				for(ll i = 1; i <= n; ++i) {
 					B[j][i] = A[i][j];
 				}
 			}
 			swap(n, m);
 			A = B;
 		}
 		ll mask = 0;
		for(ll j = 1; j <= n; ++j) {
			if(A[j][1]) mask |= (1LL << (j - 1));
		}
		ll val = inf;
		for(ll sm = 0; sm < (1LL << n); ++sm) val = min(val, __builtin_popcount(sm ^ mask) + doit(A, 2, sm, m, n, 0));
		if(val >= inf) val = -1;
		cout << val << "\n";
 	}

    return 0;
}


#include "bits/stdc++.h"
using namespace std;
typedef long long ll;
typedef pair<ll ,ll> pll;
#define F first
#define S second
#define pb push_back
#define mp make_pair
#define all(X) (X).begin(), (X).end()
#define REP(i,x,y) for(ll i = x;i <= y;++i)
#define fastio ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0)
vector<string> vec_splitter(string s) {
    for(char& c: s) c = c == ','?  ' ': c;
    stringstream ss; ss << s;
    vector<string> res;
    for(string z; ss >> z; res.push_back(z))
        ;
    return res;
}
void debug_out(vector<string> args, int idx) { cerr << endl; }
template <typename Head, typename... Tail>
void debug_out(vector<string> args, int idx, Head H, Tail... T) {
    if(idx > 0) cerr << ", ";
    stringstream ss; ss << H;
    cerr << args[idx] << " = " << ss.str();
    debug_out(args, idx + 1, T...);
}
#define debug(...) debug_out(vec_splitter(#__VA_ARGS__), 0, __VA_ARGS__)
void localTest() {
    #ifndef ONLINE_JUDGE
        freopen("inp", "r", stdin);
        freopen("out", "w", stdout);
    #endif
}
const ll N = 1e6 + 5, inf = 1e9;
ll dp[N][10];
vector<ll> submask[10];
ll doit(vector<vector<ll>> &A, ll idx, ll mask, ll n, ll m, ll fl) {
	if(idx > n) return 0;
	ll &ret = dp[idx][mask];
	if(ret != -1) return ret;
	ll curr = 0;
	for(ll j = 1; j <= m; ++j) {
		if(A[j][idx]) curr |= (1LL << (j - 1));
	}
	vector<vector<ll>> aux(m, vector<ll>(2, 0));
	// debug("haha");
	for(ll i = 0; i < 3; ++i) {
		if(mask & (1LL << i)) aux[i][0] = 1;
	}
	// debug("hehe");
	ll ans = inf;
	for(auto sm : submask[curr]) {
		// debug(idx, mask, sm);
		for(ll i = 0; i < 3; ++i) {
			if(sm & (1LL << i)) aux[i][1] = 1;
			else {
				if(i < m) aux[i][1] = 0;
			}
		}
		// for(ll i = 0; i < m; ++i) {
		// 	for(ll j = 0; j < 2; ++j) debug(i, j, aux[i][j], sm, idx, mask, curr);
		// }
		ll c1 = aux[0][0] + aux[0][1] + aux[1][0] + aux[1][1];
		if(c1 % 2 == 0) continue;
		if(m > 2) {
			c1 = aux[1][0] + aux[1][1] + aux[2][0] + aux[2][1];
			if(c1 % 2 == 0) continue;
		}
		// debug("haha");
		ans = min(ans, __builtin_popcount(sm ^ curr) + doit(A, idx + 1, sm, n, m, fl));
	}
	return ret = ans;
}
int main() {

    localTest();
    fastio;
    for(ll i = 0; i < 10; ++i) {
    	submask[i].pb(0);
    	for(ll j = i; j > 0; j = (i & (j - 1))) submask[i].pb(j);
    }
 	ll n, m;
 	cin >> n >> m;
 	vector<vector<ll>> A(n + 1, vector<ll>(m + 1, 0));
 	for(ll i = 1; i <= n; ++i) {
 		string s;
 		cin >> s;
 		for(ll j = 1; j <= m; ++j) {
 			if(s[j - 1] == '1') A[i][j] = 1;
 		}
 	}
 	if(n >= 4 && m >= 4) {
 		cout << "-1\n";
 	}
 	else if(n == 1 || m == 1) cout << "0\n";
 	else {
 		memset(dp, -1, sizeof dp);
 		if(n > m) {
 			vector<vector<ll>> B = A;
 			for(ll j = 1; j <= m; ++j) {
 				for(ll i = 1; i <= n; ++i) {
 					B[j][i] = A[i][j];
 				}
 			}
 			// debug(B.size(), B[0].size());
 			swap(n, m);
 			A = B;
 		}
 		// for(ll i = 1; i <= n; ++i) {
 		// 	for(ll j = 1; j <= m; ++j) cout << A[i][j];
 		// 	cout << "\n";
 		// }
 		// if(n > m) {
 		// 	ll mask = 0;
 		// 	for(ll j = 1; j <= m; ++j) {
 		// 		if(A[1][j]) mask |= (1LL << (j - 1));
 		// 	}
 		// 	ll val = doit(A, 2, mask, n, m, 1);
 		// 	for(auto sm : submask[mask]) val = min(val, __builtin_popcount(sm ^ mask) + doit(A, 2, sm, n, m, 1));
 		// 	if(val >= inf) val = -1;
 		// 	cout << val << "\n";
 		// } else {
		ll mask = 0;
		for(ll j = 1; j <= n; ++j) {
			if(A[j][1]) mask |= (1LL << (j - 1));
		}
		// debug(mask);
		ll val = inf;
		for(auto sm : submask[mask]) val = min(val, __builtin_popcount(sm ^ mask) + doit(A, 2, sm, m, n, 0));
		if(val >= inf) val = -1;
		cout << val << "\n";
 		// }
 	}

    return 0;
}


#include "bits/stdc++.h"
using namespace std;
typedef long long ll;
typedef pair<ll ,ll> pll;
#define F first
#define S second
#define pb push_back
#define mp make_pair
#define all(X) (X).begin(), (X).end()
#define REP(i,x,y) for(ll i = x;i <= y;++i)
#define fastio ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0)
vector<string> vec_splitter(string s) {
    for(char& c: s) c = c == ','?  ' ': c;
    stringstream ss; ss << s;
    vector<string> res;
    for(string z; ss >> z; res.push_back(z))
        ;
    return res;
}
void debug_out(vector<string> args, int idx) { cerr << endl; }
template <typename Head, typename... Tail>
void debug_out(vector<string> args, int idx, Head H, Tail... T) {
    if(idx > 0) cerr << ", ";
    stringstream ss; ss << H;
    cerr << args[idx] << " = " << ss.str();
    debug_out(args, idx + 1, T...);
}
#define debug(...) debug_out(vec_splitter(#__VA_ARGS__), 0, __VA_ARGS__)
void localTest() {
    #ifndef ONLINE_JUDGE
        freopen("inp", "r", stdin);
        freopen("out", "w", stdout);
    #endif
}
const ll N = 1e6 + 5, inf = 1e9;
ll dp[N][10];
vector<ll> submask[10];
ll doit(vector<vector<ll>> &A, ll idx, ll mask, ll n, ll m, ll fl) {
	if(idx > n) return 0;
	ll &ret = dp[idx][mask];
	if(ret != -1) return ret;
	ll curr = 0;
	for(ll j = 1; j <= m; ++j) {
		if(A[j][idx]) curr |= (1LL << (j - 1));
	}
	vector<vector<ll>> aux(m, vector<ll>(2, 0));
	// debug("haha");
	for(ll i = 0; i < 3; ++i) {
		if(mask & (1LL << i)) aux[i][0] = 1;
	}
	// debug("hehe");
	ll ans = inf;
	for(auto sm : submask[curr]) {
		// debug(idx, mask, sm);
		for(ll i = 0; i < 3; ++i) {
			if(sm & (1LL << i)) aux[i][1] = 1;
			else {
				if(i < m) aux[i][1] = 0;
			}
		}
		// for(ll i = 0; i < m; ++i) {
		// 	for(ll j = 0; j < 2; ++j) debug(i, j, aux[i][j], sm, idx, mask, curr);
		// }
		ll c1 = aux[0][0] + aux[0][1] + aux[1][0] + aux[1][1];
		if(c1 % 2 == 0) continue;
		if(m > 2) {
			c1 = aux[1][0] + aux[1][1] + aux[2][0] + aux[2][1];
			if(c1 % 2 == 0) continue;
		}
		// debug("haha");
		ans = min(ans, __builtin_popcount(sm ^ curr) + doit(A, idx + 1, sm, n, m, fl));
	}
	return ret = ans;
}
int main() {

    localTest();
    fastio;
    for(ll i = 0; i < 10; ++i) {
    	submask[i].pb(0);
    	for(ll j = i; j > 0; j = (i & (j - 1))) submask[i].pb(j);
    }
 	ll n, m;
 	cin >> n >> m;
 	vector<vector<ll>> A(n + 1, vector<ll>(m + 1, 0));
 	for(ll i = 1; i <= n; ++i) {
 		string s;
 		cin >> s;
 		for(ll j = 1; j <= m; ++j) {
 			if(s[j - 1] == '1') A[i][j] = 1;
 		}
 	}
 	if(n >= 4 && m >= 4) {
 		cout << "-1\n";
 	}
 	else if(n == 1 || m == 1) cout << "0\n";
 	else {
 		memset(dp, -1, sizeof dp);
 		if(n > m) {
 			vector<vector<ll>> B;
 			vector<ll> ele(n, 0);
 			B.pb(ele);
 			for(ll j = 1; j <= m; ++j) {
 				vector<ll> aux;
 				aux.pb(0);
 				for(ll i = 1; i <= n; ++i) {
 					aux.pb(A[i][j]);
 				}
 				B.pb(aux);
 			}
 			swap(n, m);
 			A = B;
 		}
 		// for(ll i = 1; i <= n; ++i) {
 		// 	for(ll j = 1; j <= m; ++j) cout << A[i][j];
 		// 	cout << "\n";
 		// }
 		// if(n > m) {
 		// 	ll mask = 0;
 		// 	for(ll j = 1; j <= m; ++j) {
 		// 		if(A[1][j]) mask |= (1LL << (j - 1));
 		// 	}
 		// 	ll val = doit(A, 2, mask, n, m, 1);
 		// 	for(auto sm : submask[mask]) val = min(val, __builtin_popcount(sm ^ mask) + doit(A, 2, sm, n, m, 1));
 		// 	if(val >= inf) val = -1;
 		// 	cout << val << "\n";
 		// } else {
		ll mask = 0;
		for(ll j = 1; j <= n; ++j) {
			if(A[j][1]) mask |= (1LL << (j - 1));
		}
		// debug(mask);
		ll val = inf;
		for(auto sm : submask[mask]) val = min(val, __builtin_popcount(sm ^ mask) + doit(A, 2, sm, m, n, 0));
		if(val >= inf) val = -1;
		cout << val << "\n";
 		// }
 	}

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define pii pair<int, int>
#define pll pair<ll, ll>
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define ins insert
#ifdef LOCAL
template <class S, class T>
ostream &operator<<(ostream &str, const pair<S, T> &p) {
  return (str << "{" << p.fi << ", " << p.se << "}");
}
template <template <class...> class Container, class... T>
ostream &operator<<(ostream &str, const Container<T...> &vec) {
  str << '[';
  for (auto it = vec.begin(); it != vec.end(); it++) {
    if (it != vec.begin())
      str << ", ";
    str << *it;
  }
  str << ']';
  return str;
}
#define var(x) "[" << #x << ": " << (x) << "] "
struct dbg {
  dbg() { cout << "  "; }
  ~dbg() { cout << endl; }
  template <class T> dbg &operator<<(T oth) {
    cout << oth;
    return *this;
  }
};
#else
#define var(x) 0
struct dbg {
  template <class T> dbg &operator<<(T oth) { return *this; }
};
#endif
using ll = long long;
using ull = unsigned long long;
using ld = long double;
int main(int argc, char **argv) {
  ios::sync_with_stdio(false), cin.tie(0);
  auto solve = [&]() {
    int n, m;
    cin >> n >> m;
    vector<vector<bool>> in(n, vector<bool>(m));
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < m; j++) {
        char c;
        cin >> c;
        in[i][j] = c != '0';
      }
    }
    if (min(n, m) > 3) {
      cout << "-1\n";
      return;
    }
    vector<int> real_in(max(n, m));
    for (int i = 0; i < max(n, m); i++) {
      int x = 0;
      for (int j = 0; j < min(n, m); j++)
        x |= (1 << j) * int(in[n < m ? j : i][n < m ? i : j]);
      real_in[i] = x;
    }
    vector<array<int, 8>> dp(n + 1);
    for (int i = 1; i <= n; i++) {
      dp[i].fill(INT_MAX);
      for (int k = 0; k < 8; k++) {
        int base = __builtin_popcount(k ^ real_in[i - 1]);
        auto fit = [&](int rmask, int lmask) {
          int x = (lmask << 3) | rmask;
          int a = __builtin_popcount(x & 0b110110);
          int b = __builtin_popcount(x & 0b011011);
          return (a & 1) && (b & 1);
        };
        for (int s = 0; s < 8; s++) {
          if (!fit(s, k))
            continue;
          dp[i][k] = min(dp[i][k], dp[i - 1][s] + base);
        }
      }
    }
    cout << *min_element(dp[n].begin(), dp[n].end()) << '\n';
  };
  int t;
  t = 1;
  while (t--)
    solve();
  return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define pii pair<int, int>
#define pll pair<ll, ll>
#define fi first
#define se second
#define popcount __builtin_popcount
#define pb push_back
#define mp make_pair
#define ins insert
#ifdef LOCAL
template <class S, class T>
ostream &operator<<(ostream &str, const pair<S, T> &p) {
  return (str << "{" << p.fi << ", " << p.se << "}");
}
template <template <class...> class Container, class... T>
ostream &operator<<(ostream &str, const Container<T...> &vec) {
  str << '[';
  for (auto it = vec.begin(); it != vec.end(); it++) {
    if (it != vec.begin())
      str << ", ";
    str << *it;
  }
  str << ']';
  return str;
}
#define var(x) "[" << #x << ": " << (x) << "] "
struct dbg {
  dbg() { cout << "  "; }
  ~dbg() { cout << endl; }
  template <class T> dbg &operator<<(T oth) {
    cout << oth;
    return *this;
  }
};
#else
#define var(x) 0
struct dbg {
  template <class T> dbg &operator<<(T oth) { return *this; }
};
#endif
using ll = long long;
using ull = unsigned long long;
using ld = long double;
int main(int argc, char **argv) {
  ios::sync_with_stdio(false), cin.tie(0);
  auto solve = [&]() {
    int n, m;
    cin >> n >> m;
    vector<vector<bool>> in(n, vector<bool>(m));
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < m; j++) {
        char c;
        cin >> c;
        in[i][j] = c != '0';
      }
    }
    if (min(n, m) > 3) {
      cout << "-1\n";
      return;
    }
    if (max(n, m) == 1) {
      cout << "0\n";
      return;
    }
    vector<int> real_in(max(n, m));
    for (int i = 0; i < max(n, m); i++) {
      int x = 0;
      for (int j = 0; j < min(n, m); j++)
        x |= (1 << j) * int(in[n < m ? j : i][n < m ? i : j]);
      real_in[i] = x;
    }
    dbg() << var(real_in);
    auto fit = [&](int rmask, int lmask) {
      int x = (lmask << 3) | rmask;
      int a = popcount(x & 0b110110);
      int b = popcount(x & 0b011011);
      return (a & 1) && (b & 1);
    };
    vector<array<int, 8>> dp(n + 1);
    const int INF = int(1e9);
    dp[2].fill(INF);
    for (int i = 0; i < 8; i++)
      for (int j = 0; j < 8; j++)
        if (fit(i, j)) {
          dp[2][j] = min(dp[2][j], popcount((real_in[1] << 3) | real_in[0]) ^ ((i << 3) | j));
    for (int i = 3; i <= n; i++) {
      dp[i].fill(INF);
      for (int k = 0; k < 8; k++) {
        int base = popcount(k ^ real_in[i - 1]);
        for (int s = 0; s < 8; s++) {
          if (!fit(s, k))
            continue;
          dp[i][k] = min(dp[i][k], dp[i - 1][s] + base);
        }
      }
    }
    cout << *min_element(dp[n].begin(), dp[n].end()) << '\n';
  };
  int t;
  t = 1;
  while (t--)
    solve();
  return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define pii pair<int, int>
#define pll pair<ll, ll>
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define ins insert
#ifdef LOCAL
template <class S, class T>
ostream &operator<<(ostream &str, const pair<S, T> &p) {
  return (str << "{" << p.fi << ", " << p.se << "}");
}
template <template <class...> class Container, class... T>
ostream &operator<<(ostream &str, const Container<T...> &vec) {
  str << '[';
  for (auto it = vec.begin(); it != vec.end(); it++) {
    if (it != vec.begin())
      str << ", ";
    str << *it;
  }
  str << ']';
  return str;
}
#define var(x) "[" << #x << ": " << (x) << "] "
struct dbg {
  dbg() { cout << "  "; }
  ~dbg() { cout << endl; }
  template <class T> dbg &operator<<(T oth) {
    cout << oth;
    return *this;
  }
};
#else
#define var(x) 0
struct dbg {
  template <class T> dbg &operator<<(T oth) { return *this; }
};
#endif
using ll = long long;
using ull = unsigned long long;
using ld = long double;
int main(int argc, char **argv) {
  ios::sync_with_stdio(false), cin.tie(0);
  auto solve = [&]() {
    int n, m;
    cin >> n >> m;
    vector<vector<bool>> in(n, vector<bool>(m));
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < m; j++) {
        char c;
        cin >> c;
        in[i][j] = c != '0';
      }
    }
    if (min(n, m) > 3) {
      cout << "-1\n";
      return;
    }
    vector<int> real_in(max(n, m));
    for (int i = 0; i < max(n, m); i++) {
      int x = 0;
      for (int j = 0; j < min(n, m); j++)
        x |= (1 << j) * int(in[n < m ? j : i][n < m ? i : j]);
      real_in[i] = x;
    }
    if (n < m)
      swap(n, m); // .........
    vector<array<int, 8>> dp(n + 1);
    for (int i = 1; i <= n; i++) {
      dp[i].fill(INT_MAX);
      for (int k = 0; k < 8; k++) {
        int base = __builtin_popcount(k ^ real_in[i - 1]);
        auto fit = [&](int rmask, int lmask) {
          int x = (lmask << 3) | rmask;
          int a = __builtin_popcount(x & 0b110110);
          int b = __builtin_popcount(x & 0b011011);
          return (a & 1) && (b & 1);
        };
        for (int s = 0; s < 8; s++) {
          if (!fit(s, k))
            continue;
          dp[i][k] = min(dp[i][k], dp[i - 1][s] + base);
        }
      }
    }
    cout << *min_element(dp[n].begin(), dp[n].end()) << '\n';
  };
  int t;
  t = 1;
  while (t--)
    solve();
  return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define pii pair<int, int>
#define pll pair<ll, ll>
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define ins insert
#ifdef LOCAL
template <class S, class T>
ostream &operator<<(ostream &str, const pair<S, T> &p) {
  return (str << "{" << p.fi << ", " << p.se << "}");
}
template <template <class...> class Container, class... T>
ostream &operator<<(ostream &str, const Container<T...> &vec) {
  str << '[';
  for (auto it = vec.begin(); it != vec.end(); it++) {
    if (it != vec.begin())
      str << ", ";
    str << *it;
  }
  str << ']';
  return str;
}
#define var(x) "[" << #x << ": " << (x) << "] "
struct dbg {
  dbg() { cout << "  "; }
  ~dbg() { cout << endl; }
  template <class T> dbg &operator<<(T oth) {
    cout << oth;
    return *this;
  }
};
#else
#define var(x) 0
struct dbg {
  template <class T> dbg &operator<<(T oth) { return *this; }
};
#endif
using ll = long long;
using ull = unsigned long long;
using ld = long double;
int main(int argc, char **argv) {
  ios::sync_with_stdio(false), cin.tie(0);
  auto solve = [&]() {
    int n, m;
    cin >> n >> m;
    vector<vector<bool>> kek(n, vector<bool>(m, false));
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < m; j++) {
        char c;
        cin >> c;
        kek[i][j] = c - '0';
      }
    }

    vector<vector<int>> lol(n, vector<int>(m, 0));

    vector<vector<vector<bool>>> magic(22, vector<vector<bool>>(n, vector<bool>(m, false)));
    function<void(int, int, int, int)> rec = [&](int lb, int rb, int sz, int cur) {
      if (magic[sz][lb][rb])
        return;
      if (lb + (1 << sz) > n)
        return;
      if (rb + (1 << sz) > m)
        return;
      magic[sz][lb][rb] = true;
      if (!sz)
        lol[lb][rb] += cur;
      ++cur;
      for (int i = 0; i < (sz & 1 ? 2 : 1); i++)
        for (int j = 0; j < (sz & 1 ? 2 : 1); j++)
          for (int u = 0; u < 2; u++)
            for (int v = 0; v < 2; v++)
              rec(lb + i + u * (1 << (sz - 1)), rb + i + v * (1 << (sz - 1)), sz - 1, cur);
    };
    rec(0, 0, 21, 0);
    dbg() << var(lol);
    int ans = 0;
    for (int i = 0; i < n; i++)
      for (int j = 0; j < m; j++)
        if ((lol[i][j] & 1) ^ (kek[i][j]))
          ++ans;
    cout << ans << '\n';
  };
  int t;
  t = 1;
  while (t--)
    solve();
  return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define pii pair<int, int>
#define pll pair<ll, ll>
#define fi first
#define se second
#define pb push_back
#define popcount __builtin_popcount
#define mp make_pair
#define ins insert
#ifdef LOCAL
template <class S, class T>
ostream &operator<<(ostream &str, const pair<S, T> &p) {
  return (str << "{" << p.fi << ", " << p.se << "}");
}
template <template <class...> class Container, class... T>
ostream &operator<<(ostream &str, const Container<T...> &vec) {
  str << '[';
  for (auto it = vec.begin(); it != vec.end(); it++) {
    if (it != vec.begin())
      str << ", ";
    str << *it;
  }
  str << ']';
  return str;
}
#define var(x) "[" << #x << ": " << (x) << "] "
struct dbg {
  dbg() { cout << "  "; }
  ~dbg() { cout << endl; }
  template <class T> dbg &operator<<(T oth) {
    cout << oth;
    return *this;
  }
};
#else
#define var(x) 0
struct dbg {
  template <class T> dbg &operator<<(T oth) { return *this; }
};
#endif
using ll = long long;
using ull = unsigned long long;
using ld = long double;
int main(int argc, char **argv) {
  ios::sync_with_stdio(false), cin.tie(0);
  auto solve = [&]() {
    int n, m;
    cin >> n >> m;
    vector<vector<bool>> in(n, vector<bool>(m));
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < m; j++) {
        char c;
        cin >> c;
        in[i][j] = c != '0';
      }
    }
    if (min(n, m) > 3) {
      cout << "-1\n";
      return;
    }
    vector<int> real_in(max(n, m));
    for (int i = 0; i < max(n, m); i++) {
      int x = 0;
      for (int j = 0; j < min(n, m); j++)
        x |= (1 << j) * int(in[n < m ? j : i][n < m ? i : j]);
      real_in[i] = x;
    }
    if (n < m)
      swap(n, m); // blyat 2
    vector<vector<int>> dp(n + 1, vector<int>(1 << m, 0));
    for (int i = 1; i <= n; i++) {
      fill(dp[i].begin(), dp[i].end(), int(1e9));
      for (int k = 0; k < (1 << m); k++) {
        int base = popcount(k ^ real_in[i - 1]);
        auto fit = [&](int rmask, int lmask) {
          if (m == 3) {
            int x = (lmask << 3) | rmask;
            int a = popcount(x & 0b110110);
            int b = popcount(x & 0b011011);
            return (a & 1) && (b & 1);
          } else if (m == 2) {
            return bool(popcount((rmask << 2) | lmask) & 1);
          } else
            assert(false);
        };
        for (int s = 0; s < (1 << m); s++) {
          if (!fit(s, k))
            continue;
          dp[i][k] = min(dp[i][k], dp[i - 1][s] + base);
        }
      }
    }
    cout << *min_element(dp[n].begin(), dp[n].end()) << '\n';
  };
  int t;
  t = 1;
  while (t--)
    solve();
  return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define pii pair<int, int>
#define pll pair<ll, ll>
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define ins insert
#ifdef LOCAL
template <class S, class T>
ostream &operator<<(ostream &str, const pair<S, T> &p) {
  return (str << "{" << p.fi << ", " << p.se << "}");
}
template <template <class...> class Container, class... T>
ostream &operator<<(ostream &str, const Container<T...> &vec) {
  str << '[';
  for (auto it = vec.begin(); it != vec.end(); it++) {
    if (it != vec.begin())
      str << ", ";
    str << *it;
  }
  str << ']';
  return str;
}
#define var(x) "[" << #x << ": " << (x) << "] "
struct dbg {
  dbg() { cout << "  "; }
  ~dbg() { cout << endl; }
  template <class T> dbg &operator<<(T oth) {
    cout << oth;
    return *this;
  }
};
#else
#define var(x) 0
struct dbg {
  template <class T> dbg &operator<<(T oth) { return *this; }
};
#endif
using ll = long long;
using ull = unsigned long long;
using ld = long double;
int main(int argc, char **argv) {
  ios::sync_with_stdio(false), cin.tie(0);
  auto solve = [&]() {
    int n, m;
    cin >> n >> m;
    vector<vector<bool>> in(n, vector<bool>(m));
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < m; j++) {
        char c;
        cin >> c;
        in[i][j] = c != '0';
      }
    }
    if (min(n, m) > 3) {
      cout << "-1\n";
      return;
    }
    vector<int> real_in(max(n, m));
    for (int i = 0; i < max(n, m); i++) {
      int x = 0;
      for (int j = 0; j < min(n, m); j++)
        x |= (1 << j) * int(in[n < m ? j : i][n < m ? i : j]);
      real_in[i] = x;
    }
    if (n < m)
      swap(n, m); // .........
    vector<array<int, 8>> dp(n + 1);
    for (int i = 0; i < 8; i++)
      assert(!dp[0][i]);
    for (int i = 1; i <= n; i++) {
      dp[i].fill(INT_MAX);
      for (int k = 0; k < 8; k++) {
        int base = __builtin_popcount(k ^ real_in[i - 1]);
        auto fit = [&](int rmask, int lmask) {
          int x = (lmask << 3) | rmask;
          int a = __builtin_popcount(x & 0b110110);
          int b = __builtin_popcount(x & 0b011011);
          return (a & 1) && (b & 1);
        };
        for (int s = 0; s < 8; s++) {
          if (!fit(s, k))
            continue;
          dp[i][k] = min(dp[i][k], dp[i - 1][s] + base);
        }
      }
    }
    cout << *min_element(dp[n].begin(), dp[n].end()) << '\n';
  };
  int t;
  t = 1;
  while (t--)
    solve();
  return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define pii pair<int, int>
#define pll pair<ll, ll>
#define fi first
#define se second
#define popcount __builtin_popcount
#define pb push_back
#define mp make_pair
#define ins insert
#ifdef LOCAL
template <class S, class T>
ostream &operator<<(ostream &str, const pair<S, T> &p) {
  return (str << "{" << p.fi << ", " << p.se << "}");
}
template <template <class...> class Container, class... T>
ostream &operator<<(ostream &str, const Container<T...> &vec) {
  str << '[';
  for (auto it = vec.begin(); it != vec.end(); it++) {
    if (it != vec.begin())
      str << ", ";
    str << *it;
  }
  str << ']';
  return str;
}
#define var(x) "[" << #x << ": " << (x) << "] "
struct dbg {
  dbg() { cout << "  "; }
  ~dbg() { cout << endl; }
  template <class T> dbg &operator<<(T oth) {
    cout << oth;
    return *this;
  }
};
#else
#define var(x) 0
struct dbg {
  template <class T> dbg &operator<<(T oth) { return *this; }
};
#endif
using ll = long long;
using ull = unsigned long long;
using ld = long double;
int main(int argc, char **argv) {
  ios::sync_with_stdio(false), cin.tie(0);
  auto solve = [&]() {
    int n, m;
    cin >> n >> m;
    vector<vector<bool>> in(n, vector<bool>(m));
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < m; j++) {
        char c;
        cin >> c;
        in[i][j] = c != '0';
      }
    }
    if (min(n, m) > 3) {
      cout << "-1\n";
      return;
    }
    if (max(n, m) == 1) {
      cout << "0\n";
      return;
    }
    vector<int> real_in(max(n, m));
    for (int i = 0; i < max(n, m); i++) {
      int x = 0;
      for (int j = 0; j < min(n, m); j++)
        x |= (1 << j) * int(in[n < m ? j : i][n < m ? i : j]);
      real_in[i] = x;
    }
    dbg() << var(real_in);
    auto fit = [&](int rmask, int lmask) {
      int x = (lmask << 3) | rmask;
      int a = popcount(x & 0b110110);
      int b = popcount(x & 0b011011);
      return (a & 1) && (b & 1);
    };
    vector<array<int, 8>> dp(n + 1);
    const int INF = int(1e9);
    dp[2].fill(INF);
    for (int i = 0; i < 8; i++)
      for (int j = 0; j < 8; j++)
        if (fit(j, i))
          dp[2][j] = min(dp[2][j], popcount((real_in[0] << 3) | real_in[1]) ^ ((i << 3) | j));
    for (int i = 3; i <= n; i++) {
      dp[i].fill(INF);
      for (int k = 0; k < 8; k++) {
        int base = popcount(k ^ real_in[i - 1]);
        for (int s = 0; s < 8; s++) {
          if (!fit(s, k))
            continue;
          dp[i][k] = min(dp[i][k], dp[i - 1][s] + base);
        }
      }
    }
    cout << *min_element(dp[n].begin(), dp[n].end()) << '\n';
  };
  int t;
  t = 1;
  while (t--)
    solve();
  return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define pii pair<int, int>
#define pll pair<ll, ll>
#define fi first
#define se second
#define pb push_back
#define popcount __builtin_popcount
#define mp make_pair
#define ins insert
#ifdef LOCAL
template <class S, class T>
ostream &operator<<(ostream &str, const pair<S, T> &p) {
  return (str << "{" << p.fi << ", " << p.se << "}");
}
template <template <class...> class Container, class... T>
ostream &operator<<(ostream &str, const Container<T...> &vec) {
  str << '[';
  for (auto it = vec.begin(); it != vec.end(); it++) {
    if (it != vec.begin())
      str << ", ";
    str << *it;
  }
  str << ']';
  return str;
}
#define var(x) "[" << #x << ": " << (x) << "] "
struct dbg {
  dbg() { cout << "  "; }
  ~dbg() { cout << endl; }
  template <class T> dbg &operator<<(T oth) {
    cout << oth;
    return *this;
  }
};
#else
#define var(x) 0
struct dbg {
  template <class T> dbg &operator<<(T oth) { return *this; }
};
#endif
using ll = long long;
using ull = unsigned long long;
using ld = long double;
int main(int argc, char **argv) {
  ios::sync_with_stdio(false), cin.tie(0);
  auto solve = [&]() {
    int n, m;
    cin >> n >> m;
    vector<vector<bool>> in(n, vector<bool>(m));
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < m; j++) {
        char c;
        cin >> c;
        in[i][j] = c != '0';
      }
    }
    if (min(n, m) > 3) {
      cout << "-1\n";
      return;
    }
    if (m == 1) {
      cout << "0\n";
      return;
    }
    vector<int> real_in(max(n, m));
    for (int i = 0; i < max(n, m); i++) {
      int x = 0;
      for (int j = 0; j < min(n, m); j++)
        x |= (1 << j) * int(in[n < m ? j : i][n < m ? i : j]);
      real_in[i] = x;
    }
    if (n < m)
      swap(n, m); // blyat 2
    vector<vector<int>> dp(n + 1, vector<int>(1 << m, 0));
    for (int i = 1; i <= n; i++) {
      fill(dp[i].begin(), dp[i].end(), int(1e9));
      for (int k = 0; k < (1 << m); k++) {
        int base = popcount(k ^ real_in[i - 1]);
        auto fit = [&](int rmask, int lmask) {
          if (m == 3) {
            int x = (lmask << 3) | rmask;
            int a = popcount(x & 0b110110);
            int b = popcount(x & 0b011011);
            return (a & 1) && (b & 1);
          } else if (m == 2) {
            return bool(popcount((rmask << 2) | lmask) & 1);
          } else
            assert(false);
        };
        for (int s = 0; s < (1 << m); s++) {
          if (!fit(s, k))
            continue;
          dp[i][k] = min(dp[i][k], dp[i - 1][s] + base);
        }
      }
    }
    cout << *min_element(dp[n].begin(), dp[n].end()) << '\n';
  };
  int t;
  t = 1;
  while (t--)
    solve();
  return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define pii pair<int, int>
#define pll pair<ll, ll>
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define ins insert
#ifdef LOCAL
template <class S, class T>
ostream &operator<<(ostream &str, const pair<S, T> &p) {
  return (str << "{" << p.fi << ", " << p.se << "}");
}
template <template <class...> class Container, class... T>
ostream &operator<<(ostream &str, const Container<T...> &vec) {
  str << '[';
  for (auto it = vec.begin(); it != vec.end(); it++) {
    if (it != vec.begin())
      str << ", ";
    str << *it;
  }
  str << ']';
  return str;
}
#define var(x) "[" << #x << ": " << (x) << "] "
struct dbg {
  dbg() { cout << "  "; }
  ~dbg() { cout << endl; }
  template <class T> dbg &operator<<(T oth) {
    cout << oth;
    return *this;
  }
};
#else
#define var(x) 0
struct dbg {
  template <class T> dbg &operator<<(T oth) { return *this; }
};
#endif
using ll = long long;
using ull = unsigned long long;
using ld = long double;
int main(int argc, char **argv) {
  ios::sync_with_stdio(false), cin.tie(0);
  auto solve = [&]() {
    int n;
    cin >> n;
    for (int i = 0; i < n; i++)
      cout << (i + 1) << ' ';
    cout << '\n';
  };
  int t;
  cin >> t;
  while (t--)
    solve();
  return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define pii pair<int, int>
#define pll pair<ll, ll>
#define fi first
#define se second
#define pb push_back
#define popcount __builtin_popcount
#define mp make_pair
#define ins insert
#ifdef LOCAL
template <class S, class T>
ostream &operator<<(ostream &str, const pair<S, T> &p) {
  return (str << "{" << p.fi << ", " << p.se << "}");
}
template <template <class...> class Container, class... T>
ostream &operator<<(ostream &str, const Container<T...> &vec) {
  str << '[';
  for (auto it = vec.begin(); it != vec.end(); it++) {
    if (it != vec.begin())
      str << ", ";
    str << *it;
  }
  str << ']';
  return str;
}
#define var(x) "[" << #x << ": " << (x) << "] "
struct dbg {
  dbg() { cout << "  "; }
  ~dbg() { cout << endl; }
  template <class T> dbg &operator<<(T oth) {
    cout << oth;
    return *this;
  }
};
#else
#define var(x) 0
struct dbg {
  template <class T> dbg &operator<<(T oth) { return *this; }
};
#endif
using ll = long long;
using ull = unsigned long long;
using ld = long double;
int main(int argc, char **argv) {
  ios::sync_with_stdio(false), cin.tie(0);
  auto solve = [&]() {
    int n, m;
    cin >> n >> m;
    vector<vector<bool>> in(n, vector<bool>(m));
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < m; j++) {
        char c;
        cin >> c;
        in[i][j] = c != '0';
      }
    }
    if (min(n, m) > 3) {
      cout << "-1\n";
      return;
    }
    vector<int> real_in(max(n, m));
    for (int i = 0; i < max(n, m); i++) {
      int x = 0;
      for (int j = 0; j < min(n, m); j++)
        x |= (1 << j) * int(in[n < m ? j : i][n < m ? i : j]);
      real_in[i] = x;
    }
    if (n < m)
      swap(n, m); // blyat 2
    if (m == 1) { // blyat finalniy
      cout << "0\n";
      return;
    }
    vector<vector<int>> dp(n + 1, vector<int>(1 << m, 0));
    for (int i = 1; i <= n; i++) {
      fill(dp[i].begin(), dp[i].end(), int(1e9));
      for (int k = 0; k < (1 << m); k++) {
        int base = popcount(k ^ real_in[i - 1]);
        auto fit = [&](int rmask, int lmask) {
          if (m == 3) {
            int x = (lmask << 3) | rmask;
            int a = popcount(x & 0b110110);
            int b = popcount(x & 0b011011);
            return (a & 1) && (b & 1);
          } else if (m == 2) {
            return bool(popcount((rmask << 2) | lmask) & 1);
          } else
            assert(false);
        };
        for (int s = 0; s < (1 << m); s++) {
          if (!fit(s, k))
            continue;
          dp[i][k] = min(dp[i][k], dp[i - 1][s] + base);
        }
      }
    }
    cout << *min_element(dp[n].begin(), dp[n].end()) << '\n';
  };
  int t;
  t = 1;
  while (t--)
    solve();
  return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define pii pair<int, int>
#define pll pair<ll, ll>
#define fi first
#define se second
#define popcount __builtin_popcount
#define pb push_back
#define mp make_pair
#define ins insert
#ifdef LOCAL
template <class S, class T>
ostream &operator<<(ostream &str, const pair<S, T> &p) {
  return (str << "{" << p.fi << ", " << p.se << "}");
}
template <template <class...> class Container, class... T>
ostream &operator<<(ostream &str, const Container<T...> &vec) {
  str << '[';
  for (auto it = vec.begin(); it != vec.end(); it++) {
    if (it != vec.begin())
      str << ", ";
    str << *it;
  }
  str << ']';
  return str;
}
#define var(x) "[" << #x << ": " << (x) << "] "
struct dbg {
  dbg() { cout << "  "; }
  ~dbg() { cout << endl; }
  template <class T> dbg &operator<<(T oth) {
    cout << oth;
    return *this;
  }
};
#else
#define var(x) 0
struct dbg {
  template <class T> dbg &operator<<(T oth) { return *this; }
};
#endif
using ll = long long;
using ull = unsigned long long;
using ld = long double;
int main(int argc, char **argv) {
  ios::sync_with_stdio(false), cin.tie(0);
  auto solve = [&]() {
    int n, m;
    cin >> n >> m;
    vector<vector<bool>> in(n, vector<bool>(m));
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < m; j++) {
        char c;
        cin >> c;
        in[i][j] = c != '0';
      }
    }
    if (min(n, m) > 3) {
      cout << "-1\n";
      return;
    }
    if (max(n, m) == 1) {
      cout << "0\n";
      return;
    }
    vector<int> real_in(max(n, m));
    for (int i = 0; i < max(n, m); i++) {
      int x = 0;
      for (int j = 0; j < min(n, m); j++)
        x |= (1 << j) * int(in[n < m ? j : i][n < m ? i : j]);
      real_in[i] = x;
    }
    dbg() << var(real_in);
    auto fit = [&](int rmask, int lmask) {
      int x = (lmask << 3) | rmask;
      int a = popcount(x & 0b110110);
      int b = popcount(x & 0b011011);
      return (a & 1) && (b & 1);
    };
    vector<array<int, 8>> dp(n + 1);
    const int INF = int(1e9);
    dp[2].fill(INF);
    for (int i = 0; i < 8; i++)
      for (int j = 0; j < 8; j++)
        if (fit(i, j))
          dp[2][j] = min(dp[2][j], popcount((real_in[1] << 3) | real_in[0]) ^ ((i << 3) | j));
    for (int i = 3; i <= n; i++) {
      dp[i].fill(INF);
      for (int k = 0; k < 8; k++) {
        int base = popcount(k ^ real_in[i - 1]);
        for (int s = 0; s < 8; s++) {
          if (!fit(s, k))
            continue;
          dp[i][k] = min(dp[i][k], dp[i - 1][s] + base);
        }
      }
    }
    cout << *min_element(dp[n].begin(), dp[n].end()) << '\n';
  };
  int t;
  t = 1;
  while (t--)
    solve();
  return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define pii pair<int, int>
#define pll pair<ll, ll>
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define ins insert
#ifdef LOCAL
template <class S, class T>
ostream &operator<<(ostream &str, const pair<S, T> &p) {
  return (str << "{" << p.fi << ", " << p.se << "}");
}
template <template <class...> class Container, class... T>
ostream &operator<<(ostream &str, const Container<T...> &vec) {
  str << '[';
  for (auto it = vec.begin(); it != vec.end(); it++) {
    if (it != vec.begin())
      str << ", ";
    str << *it;
  }
  str << ']';
  return str;
}
#define var(x) "[" << #x << ": " << (x) << "] "
struct dbg {
  dbg() { cout << "  "; }
  ~dbg() { cout << endl; }
  template <class T> dbg &operator<<(T oth) {
    cout << oth;
    return *this;
  }
};
#else
#define var(x) 0
struct dbg {
  template <class T> dbg &operator<<(T oth) { return *this; }
};
#endif
using ll = long long;
using ull = unsigned long long;
using ld = long double;
int main(int argc, char **argv) {
  ios::sync_with_stdio(false), cin.tie(0);
  auto solve = [&]() {
    int n, m;
    cin >> n >> m;
    vector<vector<bool>> in(n, vector<bool>(m));
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < m; j++) {
        char c;
        cin >> c;
        in[i][j] = c != '0';
      }
    }
    if (min(n, m) > 3) {
      cout << "-1\n";
      return;
    }
    vector<int> real_in(max(n, m));
    for (int i = 0; i < max(n, m); i++) {
      int x = 0;
      for (int j = 0; j < min(n, m); j++)
        x |= (1 << j) * int(in[n < m ? j : i][n < m ? i : j]);
      real_in[i] = x;
    }
    if (n < m)
      swap(n, m); // blyat 2
    vector<array<int, 8>> dp(n + 1);
    for (int i = 1; i <= n; i++) {
      dp[i].fill(int(1e9)); // blyat 1
      for (int k = 0; k < 8; k++) {
        int base = __builtin_popcount(k ^ real_in[i - 1]);
        auto fit = [&](int rmask, int lmask) {
          int x = (lmask << 3) | rmask;
          int a = __builtin_popcount(x & 0b110110);
          int b = __builtin_popcount(x & 0b011011);
          return (a & 1) && (b & 1);
        };
        for (int s = 0; s < 8; s++) {
          if (!fit(s, k))
            continue;
          dp[i][k] = min(dp[i][k], dp[i - 1][s] + base);
        }
      }
    }
    cout << *min_element(dp[n].begin(), dp[n].end()) << '\n';
  };
  int t;
  t = 1;
  while (t--)
    solve();
  return 0;
}


#include <bits/stdc++.h>
#define INF 1e9
#define int long long
using namespace std;
const int mod=1000000007;
int n,m;
char a[5][5];
int check(int x) {
    int ret=0;
    bool t[n+1][m+1];
    for (int i=0; i<n; i++)
        for (int j=0; j<m; j++)
            t[i][j]=(!(x&(1<<(m*i+j)))==0);
    for (int i=0; i<n-1; i++)
        for (int j=0; j<m-1; j++)
            if ((t[i][j]+t[i+1][j]+t[i][j+1]+t[i+1][j+1])%2==0)
                return INF;
    for (int i=0; i<n; i++)
        for (int j=0; j<m; j++)
            if (t[i][j]!=a[i][j]-'0') ret++;
    return ret;
}
signed main() {
    cin >> n >> m;
    if (n>=4&&m>=4) {
        cout << -1;
        return 0;
    }
    for (int i=0; i<n; i++)
        for (int j=0; j<m; j++) {
            cin >> a[i][j];
        }
    if (n==1||m==1) {
        cout << 0;
        return 0;
    }
    int x=n*m;
    int ans=INF;
    for (int i=0; i<(1<<(x)); i++) {
            ans=min(ans,check(i));
    }
    cout << ans;
}


#include <bits/stdc++.h>

using namespace std;
#define ll long long
#define ld long double
#define pll pair<long long,long long>
#define vll vector<long long>
#define pb push_back
#define mp make_pair
#define ff first
#define ss second
#define deb(x) cout << #x << "=" << x << endl
#define F(i,a,b) for(ll i=a;i<=b;i++)
#define RF(i,a,b) for(ll i=a;i>=b;i--)
#define in(a,n) F(i,0,n-1)cin>>a[i]
#define vi vector<int>
#define out(a,n) F(i,0,n-1)cout<<a[i]<<" ";cout<<endl
#define mod 1000000007
#define trace1(x)                cerr<<#x<<": "<<x<<endl
#define trace2(x, y)             cerr<<#x<<": "<<x<<" | "<<#y<<": "<<y<<endl
#define trace3(x, y, z)          cerr<<#x<<":" <<x<<" | "<<#y<<": "<<y<<" | "<<#z<<": "<<z<<endl
#define trace4(a, b, c, d)       cerr<<#a<<": "<<a<<" | "<<#b<<": "<<b<<" | "<<#c<<": "<<c<<" | "<<#d<<": "<<d<<endl
#define trace5(a, b, c, d, e)    cerr<<#a<<": "<<a<<" | "<<#b<<": "<<b<<" | "<<#c<<": "<<c<<" | "<<#d<<": "<<d<<" | "<<#e<< ": "<<e<<endl
#define trace6(a, b, c, d, e, f) cerr<<#a<<": "<<a<<" | "<<#b<<": "<<b<<" | "<<#c<<": "<<c<<" | "<<#d<<": "<<d<<" | "<<#e<< ": "<<e<<" | "<<#f<<": "<<f<<endl
#define int long long

int n,m;
const int N=(int)1e6+5;

int dp[N][8];
vector<string>v;

int solve(int j,int pre)
{
    if(j==m)return 0;
    int &ans=dp[j][pre];

    if(ans!=-1)return ans;
    ans=mod;

    for(int mask=0;mask<(1<<n);mask++)
    {
        int c=0;
        for(int i=0;i<n;i++)
        {
            int val=(mask&(1<<i))>0;
            c+=(val!=(v[i][j]-'0'));
        }
        int can=1;
        for(int i=0;i<n;i++)
        {
            //cout<<"h1\n";
            if(j and i+1<n)
            {
                int v1=(mask&(1<<i))>0;
                int v2=(mask&(1<<(i+1)))>0;
                int v3=(pre & (1<<i))>0;
                int v4=(pre &(1<<(i+1)))>0;
                can&=((v1+v2+v3+v4)%2)>0;
            }
        }
        if(can)ans=min(ans,c+solve(j+1,mask));

    }

    return ans;
}

void solve()
{
    memset(dp,-1,sizeof dp);
	cin>>n>>m;
    v.resize(n);

    for(auto &x:v)cin>>x;
    // for(int i=0;i<n;i++)
    // {
    //     for(int j=0;j<m;j++)cout<<v[i][j];
    //     cout<<'\n';
    // }
    if(n==1)cout<<"0";
    else if(n>3)cout<<"-1\n";
    else
    {
        cout<<solve(0,0);
    }

}

int32_t main()
{
	ios::sync_with_stdio(false);
    cin.tie(NULL);

	int t=1;
	//cin>>t;
	while(t--)solve();

}


// raj_orton

#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;

#define forr(i, n) for(int i = 0; i < n; i++)

const int inf = 1e6 + 7;

void solve() {

	int n, m;
	cin >> n >> m;

	string s[n];
	for(int i = 0; i < n; i++) {
		cin >> s[i];
	}

	vector<vector<int>> arr(n, vector<int>(m));
	forr(i, n) forr(j, m) arr[i][j] = s[i][j] - '0';

	if(n == 1) {
		cout << 0 << endl;
	} else if(n == 2) {
		int dp[m][2][2][2][2];
		forr(i, m) forr(a, 2) forr(b, 2) forr(c, 2) forr(d, 2) dp[i][a][b][c][d] = -1;

		function<int(int, int, int, int, int)> go = [&](int i, int a, int b, int c, int d) {
			if(i == m - 1) return 0;

			int &ans = dp[i][a][b][c][d];
			if(ans != -1) return ans;

			ans = inf;
			forr(na, 2) forr(nb, 2) forr(nc, 2) forr(nd, 2) {
				if((b == na) && (d == nc) && ((na + nb + nc + nd) & 1))
					ans = min(ans, go(i + 1, na, nb, nc, nd));
			}

			ans += arr[0][i] != a;
			ans += arr[0][i + 1] != b;
			ans += arr[1][i] != c;
			ans += arr[1][i + 1] != d;

			return ans;
		};

		int ans = inf;
		forr(a, 2) forr(b, 2) forr(c, 2) forr(d, 2) {
			if((a + b + c + d) & 1)
				ans = min(ans, go(0, a, b, c, d));
		}
		cout << ans << endl;
	} else if(n == 3) {
		int dp[m][2][2][2][2][2][2];
		forr(i, m) forr(a, 2) forr(b, 2) forr(c, 2) forr(d, 2) forr(e, 2) forr(f, 2) dp[i][a][b][c][d][e][f] = -1;

		function<int(int, int, int, int, int, int, int)> go = [&](int i, int a, int b, int c, int d, int e, int f) {
			if(i == m - 1) return 0;

			int &ans = dp[i][a][b][c][d][e][f];
			if(ans != -1) return ans;

			ans = inf;
			forr(na, 2) forr(nb, 2) forr(nc, 2) forr(nd, 2) forr(ne, 2) forr(nf, 2) {
				if((b == na) && (d == nc) && (f == ne) && ((na + nb + nc + nd) & 1) && ((nc + nd + ne + nf) & 1))
					ans = min(ans, go(i + 1, na, nb, nc, nd, ne, nf));
			}

			ans += arr[0][i] != a;
			ans += arr[0][i + 1] != b;
			ans += arr[1][i] != c;
			ans += arr[1][i + 1] != d;
			ans += arr[2][i] != e;
			ans += arr[2][i + 1] != f;

			return ans;
		};

		int ans = inf;
		forr(a, 2) forr(b, 2) forr(c, 2) forr(d, 2) forr(e, 2) forr(f, 2) {
			if(((a + b + c + d) & 1) && ((c + d + e + f) & 1))
				ans = min(ans, go(0, a, b, c, d, e, f));
		}
		cout << ans << endl;
	} else {
		cout << -1 << endl;
	}

}

signed main() {
	ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); cerr.tie(0);
	// int t; cin >> t; for(int i = 1; i <= t; i++) //cout << "Case #" << i << ": ",
	solve();
	return 0;
}


// raj_orton

#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;

#define forr(i, n) for(int i = 0; i < n; i++)

const int N = 5e5 + 6, inf = 1e9 + 7;
int dp[3][N][2][2][2][2];
string s[N];
int arr[3][N];
int n, m;

int go(int i, int j, int a, int b, int c, int d) {
	if(i == n - 1 || j == m - 1) return 0;

	int &ans = dp[i][j][a][b][c][d];
	if(ans != -1) return ans;

	ans = inf;
	int aa = arr[i][j] != a;
	int bb = arr[i][j + 1] != b;
	int cc = arr[i + 1][j] != c;
	int dd = arr[i + 1][j + 1] != d;

	int row = inf;
	forr(na, 2) forr(nb, 2) forr(nc, 2) forr(nd, 2) {
		if(na == b && nc == d && ((na + nb + nc + nd) & 1)) row = min(row, go(i, j + 1, na, nb, nc, nd) - (bb + dd) * (j != m - 2));
	}

	int col = inf;
	forr(na, 2) forr(nb, 2) forr(nc, 2) forr(nd, 2) {
		if(na == c && nb == d && ((na + nb + nc + nd) & 1)) col = min(col, go(i + 1, j, na, nb, nc, nd) - (cc + dd) * (i != n - 2));
	}
	ans = min(ans, row + col + aa + bb + cc + dd);
	return ans;

}

void solve() {

	cin >> n >> m;

	for(int i = 0; i < n; i++) {
		cin >> s[i];
	}

	if(n >= 4) {
		cout << -1 << endl;
		return;
	}

	if(n == 1) {
		cout << 0 << endl;
		return;
	}

	for(int i = 0; i < n; i++) {
		for(int j = 0; j < m; j++) {
			arr[i][j] = s[i][j] - '0';
		}
	}

	forr(i, 3) forr(j, m) forr(a, 2) forr(b, 2) forr(c, 2) forr(d, 2) dp[i][j][a][b][c][d] = -1;

	int ans = inf;
	forr(a, 2) forr(b, 2) forr(c, 2) forr(d, 2) {
		int cur = a + b + c + d;
		if(cur & 1) ans = min(ans, go(0, 0, a, b, c, d));
	}
	cout << ans << endl;

}

signed main() {
	ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); cerr.tie(0);
	// int t; cin >> t; for(int i = 1; i <= t; i++) //cout << "Case #" << i << ": ",
	solve();
	return 0;
}


// raj_orton

#include <bits/stdc++.h>
// #define int long long
#define endl '\n'
using namespace std;

#define forr(i, n) for(int i = 0; i < n; i++)

const int inf = 1e6 + 7;

void solve() {

	int n, m;
	cin >> n >> m;

	string s[n];
	for(int i = 0; i < n; i++) {
		cin >> s[i];
	}

	vector<vector<int>> arr(n, vector<int>(m));
	forr(i, n) forr(j, m) arr[i][j] = s[i][j] - '0';

	if(n == 1) {
		cout << 0 << endl;
	} else if(n == 2) {
		int dp[m][2][2][2][2];
		forr(i, m) forr(a, 2) forr(b, 2) forr(c, 2) forr(d, 2) dp[i][a][b][c][d] = -1;

		function<int(int, int, int, int, int)> go = [&](int i, int a, int b, int c, int d) -> int {
			if(i == m - 1) return 0;

			int &ans = dp[i][a][b][c][d];
			if(ans != -1) return ans;

			ans = inf;
			forr(na, 2) forr(nb, 2) forr(nc, 2) forr(nd, 2) {
				if(((na + nb + nc + nd) & 1))
					ans = min(ans, go(i + 1, na, nb, nc, nd) + (b != na) + (d != nc));
			}

			ans += arr[0][i] != a;
			ans += arr[0][i + 1] != b;
			ans += arr[1][i] != c;
			ans += arr[1][i + 1] != d;

			return ans;
		};

		int ans = inf;
		forr(a, 2) forr(b, 2) forr(c, 2) forr(d, 2) {
			if((a + b + c + d) & 1)
				ans = min(ans, go(0, a, b, c, d));
		}
		cout << ans << endl;
	} else if(n == 3) {
		int dp[m][2][2][2][2][2][2];
		forr(i, m) forr(a, 2) forr(b, 2) forr(c, 2) forr(d, 2) forr(e, 2) forr(f, 2) dp[i][a][b][c][d][e][f] = -1;

		function<int(int, int, int, int, int, int, int)> go = [&](int i, int a, int b, int c, int d, int e, int f) -> int {
			if(i == m - 1) return 0;

			int &ans = dp[i][a][b][c][d][e][f];
			if(ans != -1) return ans;

			ans = inf;
			forr(na, 2) forr(nb, 2) forr(nc, 2) forr(nd, 2) forr(ne, 2) forr(nf, 2) {
				if(((na + nb + nc + nd) & 1) && ((nc + nd + ne + nf) & 1))
					ans = min(ans, go(i + 1, na, nb, nc, nd, ne, nf) + (b != na) + (d != nc) + (f != ne));
			}

			ans += arr[0][i] != a;
			ans += arr[0][i + 1] != b;
			ans += arr[1][i] != c;
			ans += arr[1][i + 1] != d;
			ans += arr[2][i] != e;
			ans += arr[2][i + 1] != f;

			return ans;
		};

		int ans = inf;
		forr(a, 2) forr(b, 2) forr(c, 2) forr(d, 2) forr(e, 2) forr(f, 2) {
			if(((a + b + c + d) & 1) && ((c + d + e + f) & 1))
				ans = min(ans, go(0, a, b, c, d, e, f));
		}
		cout << ans << endl;
	} else {
		cout << -1 << endl;
	}

}

signed main() {
	ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); cerr.tie(0);
	// int t; cin >> t; for(int i = 1; i <= t; i++) //cout << "Case #" << i << ": ",
	solve();
	return 0;
}


// raj_orton

#include <bits/stdc++.h>
// #define int long long
#define endl '\n'
using namespace std;

#define forr(i, n) for(int i = 0; i < n; i++)

const int N = 5e5 + 6, inf = 1e9 + 7;

void solve() {

	int n, m;
	cin >> n >> m;

	string s[n];
	for(int i = 0; i < n; i++) {
		cin >> s[i];
	}

	vector<vector<int>> arr(n, vector<int>(m));
	forr(i, n) forr(j, m) arr[i][j] = s[i][j] - '0';

	if(n == 1) {
		cout << 0 << endl;
	} else if(n == 2) {
		int dp[m][2][2][2][2];
		forr(i, m) forr(a, 2) forr(b, 2) forr(c, 2) forr(d, 2) dp[i][a][b][c][d] = -1;

		function<int(int, int, int, int, int)> go = [&](int i, int a, int b, int c, int d) {
			if(i == m - 1) return 0;

			int &ans = dp[i][a][b][c][d];
			if(ans != -1) return ans;

			ans = inf;
			forr(na, 2) forr(nb, 2) forr(nc, 2) forr(nd, 2) {
				if((b == na) && (d == nc) && ((na + nb + nc + nd) & 1))
					ans = min(ans, go(i + 1, na, nb, nc, nd));
			}

			ans += arr[0][i] != a;
			ans += arr[0][i + 1] != b;
			ans += arr[1][i] != c;
			ans += arr[1][i + 1] != d;

			return ans;
		};

		int ans = inf;
		forr(a, 2) forr(b, 2) forr(c, 2) forr(d, 2) {
			if((a + b + c + d) & 1)
				ans = min(ans, go(0, a, b, c, d));
		}
		cout << ans << endl;
	} else if(n == 3) {
		int dp[m][2][2][2][2][2][2];
		forr(i, m) forr(a, 2) forr(b, 2) forr(c, 2) forr(d, 2) forr(e, 2) forr(f, 2) dp[i][a][b][c][d][e][f] = -1;

		function<int(int, int, int, int, int, int, int)> go = [&](int i, int a, int b, int c, int d, int e, int f) {
			if(i == m - 1) return 0;

			int &ans = dp[i][a][b][c][d][e][f];
			if(ans != -1) return ans;

			ans = inf;
			forr(na, 2) forr(nb, 2) forr(nc, 2) forr(nd, 2) forr(ne, 2) forr(nf, 2) {
				if((b == na) && (d == nc) && (f == ne) && ((na + nb + nc + nd) & 1) && ((nc + nd + ne + nf) & 1))
					ans = min(ans, go(i + 1, na, nb, nc, nd, ne, nf));
			}

			ans += arr[0][i] != a;
			ans += arr[0][i + 1] != b;
			ans += arr[1][i] != c;
			ans += arr[1][i + 1] != d;
			ans += arr[2][i] != e;
			ans += arr[2][i + 1] != f;

			return ans;
		};

		int ans = inf;
		forr(a, 2) forr(b, 2) forr(c, 2) forr(d, 2) forr(e, 2) forr(f, 2) {
			if(((a + b + c + d) & 1) && ((c + d + e + f) & 1))
				ans = min(ans, go(0, a, b, c, d, e, f));
		}
		cout << ans << endl;
	} else {
		cout << -1 << endl;
	}

}

signed main() {
	ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); cerr.tie(0);
	// int t; cin >> t; for(int i = 1; i <= t; i++) //cout << "Case #" << i << ": ",
	solve();
	return 0;
}


// raj_orton

#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;

#define forr(i, n) for(int i = 0; i < n; i++)

const int N = 5e5 + 6, inf = 1e9 + 7;
int dp[3][N][2][2][2][2];
string s[N];
int arr[3][N];
int n, m;

int go(int i, int j, int a, int b, int c, int d) {
	if(i == n - 1 || j == m - 1) return 0;

	int &ans = dp[i][j][a][b][c][d];
	if(ans != -1) return ans;

	ans = inf;
	int aa = arr[i][j] != a;
	int bb = arr[i][j + 1] != b;
	int cc = arr[i + 1][j] != c;
	int dd = arr[i + 1][j + 1] != d;

	int row = inf;
	forr(na, 2) forr(nb, 2) forr(nc, 2) forr(nd, 2) {
		if(na == b && nc == d && ((na + nb + nc + nd) & 1)) row = min(row, go(i, j + 1, na, nb, nc, nd) - (bb + dd) * (j + 1 < m - 1));
	}

	int col = inf;
	forr(na, 2) forr(nb, 2) forr(nc, 2) forr(nd, 2) {
		if(na == c && nb == d && ((na + nb + nc + nd) & 1)) col = min(col, go(i + 1, j, na, nb, nc, nd) - (cc + dd) * (i + 1 < n - 1));
	}
	ans = min(ans, row + col + aa + bb + cc + dd);
	return ans;

}

void solve() {

	cin >> n >> m;

	for(int i = 0; i < n; i++) {
		cin >> s[i];
	}

	if(n >= 4) {
		cout << -1 << endl;
		return;
	}

	if(n == 1) {
		cout << 0 << endl;
		return;
	}

	for(int i = 0; i < n; i++) {
		for(int j = 0; j < m; j++) {
			arr[i][j] = s[i][j] - '0';
		}
	}

	forr(i, n) forr(j, m) forr(a, 2) forr(b, 2) forr(c, 2) forr(d, 2) dp[i][j][a][b][c][d] = -1;

	int ans = inf;
	forr(a, 2) forr(b, 2) forr(c, 2) forr(d, 2) {
		int cur = a + b + c + d;
		if(cur & 1) ans = min(ans, go(0, 0, a, b, c, d));
	}
	cout << ans << endl;

}

signed main() {
	ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); cerr.tie(0);
	// int t; cin >> t; for(int i = 1; i <= t; i++) //cout << "Case #" << i << ": ",
	solve();
	return 0;
}


// raj_orton

#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;

#define forr(i, n) for(int i = 0; i < n; i++)

const int inf = 1e6 + 7;

void solve() {

	int n, m;
	cin >> n >> m;

	string s[n];
	for(int i = 0; i < n; i++) {
		cin >> s[i];
	}

	vector<vector<int>> arr(n, vector<int>(m));
	forr(i, n) forr(j, m) arr[i][j] = s[i][j] - '0';

	if(n == 1) {
		cout << 0 << endl;
	} else if(n == 2) {
		int dp[m][2][2][2][2];
		forr(i, m) forr(a, 2) forr(b, 2) forr(c, 2) forr(d, 2) dp[i][a][b][c][d] = -1;

		function<int(int, int, int, int, int)> go = [&](int i, int a, int b, int c, int d) -> int {
			if(i == m - 1) return 0;

			int &ans = dp[i][a][b][c][d];
			if(ans != -1) return ans;

			ans = inf;
			forr(na, 2) forr(nb, 2) forr(nc, 2) forr(nd, 2) {
				if(((na + nb + nc + nd) & 1))
					ans = min(ans, go(i + 1, na, nb, nc, nd) + (b != na) + (d != nc));
			}

			ans += arr[0][i] != a;
			ans += arr[0][i + 1] != b;
			ans += arr[1][i] != c;
			ans += arr[1][i + 1] != d;

			return ans;
		};

		int ans = inf;
		forr(a, 2) forr(b, 2) forr(c, 2) forr(d, 2) {
			if((a + b + c + d) & 1)
				ans = min(ans, go(0, a, b, c, d));
		}
		cout << ans << endl;
	} else if(n == 3) {
		int dp[m][2][2][2][2][2][2];
		forr(i, m) forr(a, 2) forr(b, 2) forr(c, 2) forr(d, 2) forr(e, 2) forr(f, 2) dp[i][a][b][c][d][e][f] = -1;

		function<int(int, int, int, int, int, int, int)> go = [&](int i, int a, int b, int c, int d, int e, int f) -> int {
			if(i == m - 1) return 0;

			int &ans = dp[i][a][b][c][d][e][f];
			if(ans != -1) return ans;

			ans = inf;
			forr(na, 2) forr(nb, 2) forr(nc, 2) forr(nd, 2) forr(ne, 2) forr(nf, 2) {
				if(((na + nb + nc + nd) & 1) && ((nc + nd + ne + nf) & 1))
					ans = min(ans, go(i + 1, na, nb, nc, nd, ne, nf) + (b != na) + (d != nc) + (f != ne));
			}

			ans += arr[0][i] != a;
			ans += arr[0][i + 1] != b;
			ans += arr[1][i] != c;
			ans += arr[1][i + 1] != d;
			ans += arr[2][i] != e;
			ans += arr[2][i + 1] != f;

			return ans;
		};

		int ans = inf;
		forr(a, 2) forr(b, 2) forr(c, 2) forr(d, 2) forr(e, 2) forr(f, 2) {
			if(((a + b + c + d) & 1) && ((c + d + e + f) & 1))
				ans = min(ans, go(0, a, b, c, d, e, f));
		}
		cout << ans << endl;
	} else {
		cout << -1 << endl;
	}

}

signed main() {
	ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); cerr.tie(0);
	// int t; cin >> t; for(int i = 1; i <= t; i++) //cout << "Case #" << i << ": ",
	solve();
	return 0;
}


// raj_orton

#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;

#define forr(i, n) for(int i = 0; i < n; i++)

const int inf = 1e6 + 7;

void solve() {

	int n, m;
	cin >> n >> m;

	string s[n];
	for(int i = 0; i < n; i++) {
		cin >> s[i];
	}

	vector<vector<int>> arr(n, vector<int>(m));
	forr(i, n) forr(j, m) arr[i][j] = s[i][j] - '0';

	if(n == 1) {
		cout << 0 << endl;
	} else if(n == 2) {
		int dp[m][2][2][2][2];
		forr(i, m) forr(a, 2) forr(b, 2) forr(c, 2) forr(d, 2) dp[i][a][b][c][d] = -1;

		function<int(int, int, int, int, int)> go = [&](int i, int a, int b, int c, int d) -> int {
			if(i == m - 1) return 0;

			int &ans = dp[i][a][b][c][d];
			if(ans != -1) return ans;

			ans = inf;
			forr(na, 2) forr(nb, 2) forr(nc, 2) forr(nd, 2) {
				if((b == na) && (d == nc) && ((na + nb + nc + nd) & 1))
					ans = min(ans, go(i + 1, na, nb, nc, nd));
			}

			ans += arr[0][i] != a;
			ans += arr[0][i + 1] != b;
			ans += arr[1][i] != c;
			ans += arr[1][i + 1] != d;

			return ans;
		};

		int ans = inf;
		forr(a, 2) forr(b, 2) forr(c, 2) forr(d, 2) {
			if((a + b + c + d) & 1)
				ans = min(ans, go(0, a, b, c, d));
		}
		cout << ans << endl;
	} else if(n == 3) {
		int dp[m][2][2][2][2][2][2];
		forr(i, m) forr(a, 2) forr(b, 2) forr(c, 2) forr(d, 2) forr(e, 2) forr(f, 2) dp[i][a][b][c][d][e][f] = -1;

		function<int(int, int, int, int, int, int, int)> go = [&](int i, int a, int b, int c, int d, int e, int f) -> int {
			if(i == m - 1) return 0;

			int &ans = dp[i][a][b][c][d][e][f];
			if(ans != -1) return ans;

			ans = inf;
			forr(na, 2) forr(nb, 2) forr(nc, 2) forr(nd, 2) forr(ne, 2) forr(nf, 2) {
				if((b == na) && (d == nc) && (f == ne) && ((na + nb + nc + nd) & 1) && ((nc + nd + ne + nf) & 1))
					ans = min(ans, go(i + 1, na, nb, nc, nd, ne, nf));
			}

			ans += arr[0][i] != a;
			ans += arr[0][i + 1] != b;
			ans += arr[1][i] != c;
			ans += arr[1][i + 1] != d;
			ans += arr[2][i] != e;
			ans += arr[2][i + 1] != f;

			return ans;
		};

		int ans = inf;
		forr(a, 2) forr(b, 2) forr(c, 2) forr(d, 2) forr(e, 2) forr(f, 2) {
			if(((a + b + c + d) & 1) && ((c + d + e + f) & 1))
				ans = min(ans, go(0, a, b, c, d, e, f));
		}
		cout << ans << endl;
	} else {
		cout << -1 << endl;
	}

}

signed main() {
	ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); cerr.tie(0);
	// int t; cin >> t; for(int i = 1; i <= t; i++) //cout << "Case #" << i << ": ",
	solve();
	return 0;
}


// raj_orton

#include <bits/stdc++.h>
// #define int long long
#define endl '\n'
using namespace std;

#define forr(i, n) for(int i = 0; i < n; i++)

const int inf = 1e6 + 7;

void solve() {

	int n, m;
	cin >> n >> m;

	string s[n];
	for(int i = 0; i < n; i++) {
		cin >> s[i];
	}

	vector<vector<int>> arr(n, vector<int>(m));
	forr(i, n) forr(j, m) arr[i][j] = s[i][j] - '0';

	if(n == 1) {
		cout << 0 << endl;
	} else if(n == 2) {
		int dp[m][2][2][2][2];
		forr(i, m) forr(a, 2) forr(b, 2) forr(c, 2) forr(d, 2) dp[i][a][b][c][d] = -1;

		function<int(int, int, int, int, int)> go = [&](int i, int a, int b, int c, int d) {
			if(i == m - 1) return 0;

			int &ans = dp[i][a][b][c][d];
			if(ans != -1) return ans;

			ans = inf;
			forr(na, 2) forr(nb, 2) forr(nc, 2) forr(nd, 2) {
				if((b == na) && (d == nc) && ((na + nb + nc + nd) & 1))
					ans = min(ans, go(i + 1, na, nb, nc, nd));
			}

			ans += arr[0][i] != a;
			ans += arr[0][i + 1] != b;
			ans += arr[1][i] != c;
			ans += arr[1][i + 1] != d;

			return ans;
		};

		int ans = inf;
		forr(a, 2) forr(b, 2) forr(c, 2) forr(d, 2) {
			if((a + b + c + d) & 1)
				ans = min(ans, go(0, a, b, c, d));
		}
		cout << ans << endl;
	} else if(n == 3) {
		int dp[m][2][2][2][2][2][2];
		forr(i, m) forr(a, 2) forr(b, 2) forr(c, 2) forr(d, 2) forr(e, 2) forr(f, 2) dp[i][a][b][c][d][e][f] = -1;

		function<int(int, int, int, int, int, int, int)> go = [&](int i, int a, int b, int c, int d, int e, int f) {
			if(i == m - 1) return 0;

			int &ans = dp[i][a][b][c][d][e][f];
			if(ans != -1) return ans;

			ans = inf;
			forr(na, 2) forr(nb, 2) forr(nc, 2) forr(nd, 2) forr(ne, 2) forr(nf, 2) {
				if((b == na) && (d == nc) && (f == ne) && ((na + nb + nc + nd) & 1) && ((nc + nd + ne + nf) & 1))
					ans = min(ans, go(i + 1, na, nb, nc, nd, ne, nf));
			}

			ans += arr[0][i] != a;
			ans += arr[0][i + 1] != b;
			ans += arr[1][i] != c;
			ans += arr[1][i + 1] != d;
			ans += arr[2][i] != e;
			ans += arr[2][i + 1] != f;

			return ans;
		};

		int ans = inf;
		forr(a, 2) forr(b, 2) forr(c, 2) forr(d, 2) forr(e, 2) forr(f, 2) {
			if(((a + b + c + d) & 1) && ((c + d + e + f) & 1))
				ans = min(ans, go(0, a, b, c, d, e, f));
		}
		cout << ans << endl;
	} else {
		cout << -1 << endl;
	}

}

signed main() {
	ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); cerr.tie(0);
	// int t; cin >> t; for(int i = 1; i <= t; i++) //cout << "Case #" << i << ": ",
	solve();
	return 0;
}


// raj_orton

#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;

#define forr(i, n) for(int i = 0; i < n; i++)

const int N = 5e5 + 6, inf = 1e9 + 7;
int dp[3][N][2][2][2][2];
string s[N];
int arr[3][N];
int n, m;

int go(int i, int j, int a, int b, int c, int d) {
	if(i == n - 1 || j == m - 1) return 0;

	int &ans = dp[i][j][a][b][c][d];
	if(ans != -1) return ans;

	ans = inf;
	int val = 0;
	val += arr[i][j] != a;
	val += arr[i][j + 1] != b;
	val += arr[i + 1][j] != c;
	val += arr[i + 1][j + 1] != d;

	int row = inf;
	forr(na, 2) forr(nb, 2) forr(nc, 2) forr(nd, 2) {
		if(na == b && nc == d && ((na + nb + nc + nd) & 1)) row = min(row, go(i, j + 1, na, nb, nc, nd));
	}

	int col = inf;
	forr(na, 2) forr(nb, 2) forr(nc, 2) forr(nd, 2) {
		if(na == c && nb == d && ((na + nb + nc + nd) & 1)) col = min(col, go(i + 1, j, na, nb, nc, nd));
	}
	ans = min(ans, row + col + val);
	return ans;

}

void solve() {

	cin >> n >> m;

	for(int i = 0; i < n; i++) {
		cin >> s[i];
	}

	if(n >= 4) {
		cout << -1 << endl;
		return;
	}

	if(n == 1) {
		cout << 0 << endl;
		return;
	}

	for(int i = 0; i < n; i++) {
		for(int j = 0; j < m; j++) {
			arr[i][j] = s[i][j] - '0';
		}
	}

	forr(i, 3) forr(j, m) forr(a, 2) forr(b, 2) forr(c, 2) forr(d, 2) dp[i][j][a][b][c][d] = -1;

	int ans = inf;
	forr(a, 2) forr(b, 2) forr(c, 2) forr(d, 2) {
		int cur = a + b + c + d;
		if(cur & 1) ans = min(ans, go(0, 0, a, b, c, d));
	}
	cout << ans / 2 << endl;

}

signed main() {
	ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); cerr.tie(0);
	// int t; cin >> t; for(int i = 1; i <= t; i++) //cout << "Case #" << i << ": ",
	solve();
	return 0;
}


// raj_orton

#include <bits/stdc++.h>
// #define int long long
#define endl '\n'
using namespace std;

#define forr(i, n) for(int i = 0; i < n; i++)

const int inf = 1e7;

void solve() {

	int n, m;
	cin >> n >> m;

	string s[n];
	for(int i = 0; i < n; i++) {
		cin >> s[i];
	}

	vector<vector<int>> arr(n, vector<int>(m));
	forr(i, n) forr(j, m) arr[i][j] = s[i][j] - '0';

	if(n == 1) {
		cout << 0 << endl;
	} else if(n == 2) {
		int dp[m][2][2];
		forr(i, m) forr(a, 2) forr(b, 2) dp[i][a][b] = -1;

		function<int(int, int, int)> go = [&](int i, int a, int b) -> int {
			if(i == m) return 0;

			int &ans = dp[i][a][b];
			if(ans != -1) return ans;

			ans = inf;
			forr(na, 2) forr(nb, 2) {
				if((a + b + na + nb) & 1) {
					ans = min(ans, go(i + 1, na, nb));
				}
			}

			ans += arr[0][i] != a;
			ans += arr[1][i] != b;

			return ans;
		};

		int ans = inf;
		forr(a, 2) forr(b, 2) {
			ans = min(ans, go(0, a, b));
		}
		cout << ans << endl;
	} else if(n == 3) {
		int dp[m][2][2][2];
		forr(i, m) forr(a, 2) forr(b, 2) forr(c, 2) dp[i][a][b][c] = -1;

		function<int(int, int, int, int)> go = [&](int i, int a, int b, int c) -> int {
			if(i == m) return 0;

			int &ans = dp[i][a][b][c];
			if(ans != -1) return ans;

			ans = inf;
			forr(na, 2) forr(nb, 2) forr(nc, 2) {
				if(((a + b + na + nb) & 1) && ((b + c + nb + nc) & 1))
					ans = min(ans, go(i + 1, na, nb, nc));
			}

			ans += arr[0][i] != a;
			ans += arr[1][i] != b;
			ans += arr[2][i] != c;

			return ans;
		};

		int ans = inf;
		forr(a, 2) forr(b, 2) forr(c, 2) {
				ans = min(ans, go(0, a, b, c));
		}
		cout << ans << endl;
	} else {
		cout << -1 << endl;
	}

}

signed main() {
	ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); cerr.tie(0);
	// int t; cin >> t; for(int i = 1; i <= t; i++) //cout << "Case #" << i << ": ",
	solve();
	return 0;
}


// raj_orton

#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;

#define forr(i, n) for(int i = 0; i < n; i++)

const int N = 1e6 + 6, inf = 1e9 + 7;
int dp[3][N][2][2][2][2];
string s[N];
int arr[3][N];
int n, m;

int go(int i, int j, int a, int b, int c, int d) {
	if(i == n - 1 || j == m - 1) return 0;

	int &ans = dp[i][j][a][b][c][d];
	if(ans != -1) return ans;

	ans = inf;
	int val = 0;
	val += arr[i][j] != a;
	val += arr[i][j + 1] != b;
	val += arr[i + 1][j] != c;
	val += arr[i + 1][j + 1] != d;

	int row = inf;
	forr(na, 2) forr(nb, 2) forr(nc, 2) forr(nd, 2) {
		if(na == b && nc == d && ((na + nb + nc + nd) & 1)) row = min(row, go(i, j + 1, na, nb, nc, nd));
	}

	int col = inf;
	forr(na, 2) forr(nb, 2) forr(nc, 2) forr(nd, 2) {
		if(na == c && nb == d && ((na + nb + nc + nd) & 1)) col = min(col, go(i + 1, j, na, nb, nc, nd));
	}
	ans = min(ans, row + col + val);
	return ans;

}

void solve() {

	cin >> n >> m;

	for(int i = 0; i < n; i++) {
		cin >> s[i];
	}

	if(n >= 4) {
		cout << -1 << endl;
		return;
	}

	if(n == 1) {
		cout << 0 << endl;
		return;
	}

	for(int i = 0; i < n; i++) {
		for(int j = 0; j < m; j++) {
			arr[i][j] = s[i][j] - '0';
		}
	}

	forr(i, 3) forr(j, m) forr(a, 2) forr(b, 2) forr(c, 2) forr(d, 2) dp[i][j][a][b][c][d] = -1;

	int ans = inf;
	forr(a, 2) forr(b, 2) forr(c, 2) forr(d, 2) {
		int cur = a + b + c + d;
		if(cur & 1) ans = min(ans, go(0, 0, a, b, c, d));
	}
	cout << ans / 2 << endl;

}

signed main() {
	ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); cerr.tie(0);
	// int t; cin >> t; for(int i = 1; i <= t; i++) //cout << "Case #" << i << ": ",
	solve();
	return 0;
}


#include <iostream>
#include <vector>
#include <list>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <string>
#include <algorithm>
#include <cmath>
#include <bitset>
#include <climits>
#include <iomanip>
#include <set>
#include <numeric>

#define long long long int

using namespace std;

int main() {
    ios::sync_with_stdio(false);

    int n, m; cin >> n >> m;

    vector<vector<int>> a(n, vector<int>(m));

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++)  {
            char c; cin >> c;
            a[i][j] = c == '1';
        }
    }

    if (n > 3 && m > 3) {
        cout << -1 << endl;
        return 0;
    }

    if (n > 3) {
        vector<vector<int>> aa(m, vector<int>(n));
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                aa[j][i] = a[i][j];
            }
        }
        a = aa;
        swap(n, m);
    }

    int even_even = 0;
    int even_odd = 0;
    int odd_even = 0;
    int odd_odd = 0;

    for (int i = 0; i < m; i += 2) {
        if (a[0][i] == a[1][i]) {
            even_even++;
        } else {
            even_odd++;
        }
    }
    for (int i = 1; i < m; i += 2) {
        if (a[0][i] == a[1][i]) {
            odd_even++;
        } else {
            odd_odd++;
        }
    }

    if (n == 2) {
        cout << min(even_odd + odd_even, even_even + odd_odd) << endl;
        return 0;
    }

    int rr = INT_MAX;

    for (int e = 0; e <= 1; e++) {
        for (int change = 0; change <= 1; change++) {
//            cout << e << " " << change << endl;
            vector<int> changed_top(m);
            for (int i = 0; i < m; i++) {
                changed_top[i] = ((a[0][i] + a[1][i] + e) & 1) != (i & 1);
            }
            vector<int> changed_top_inf(m);
            vector<int> changed_bottom(m);
            changed_bottom[0] = change;
            int res = change + accumulate(changed_top.begin(), changed_top.end(), 0);

            for (int i = 1; i < m; i++) {
                int ok = (a[1][i - 1] + a[1][i] + a[2][i - 1] + a[2][i] + changed_top_inf[i - 1] + changed_bottom[i - 1]) % 2 == 1;
                if (changed_top[i]) {
                    if (!ok) {
                        changed_top_inf[i] = 1;
                    }
                } else {
                    if (!ok) {
                        changed_bottom[i] = 1;
                        res++;
                    }
                }
            }

//            for (int i = 0; i < m; i++) {
//                cout << changed_top[i] << " ";
//            }
//            cout << endl;
//            for (int i = 0; i < m; i++) {
//                cout << changed_top_inf[i] << " ";
//            }
//            cout << endl;
//            for (int i = 0; i < m; i++) {
//                cout << changed_bottom[i] << " ";
//            }
//            cout << endl;
//
//            cout << res << endl;
            rr = min(rr, res);
        }
    }

    cout << rr;

    return 0;
}


#include <iostream>
#include <vector>
#include <list>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <string>
#include <algorithm>
#include <cmath>
#include <bitset>
#include <climits>
#include <iomanip>
#include <set>
#include <numeric>

#define long long long int

using namespace std;

int main() {
    ios::sync_with_stdio(false);

    int n, m; cin >> n >> m;

    vector<vector<int>> a(n, vector<int>(m));

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++)  {
            char c; cin >> c;
            a[i][j] = c == '1';
        }
    }

    if (n > 3 && m > 3) {
        cout << -1 << endl;
        return 0;
    }

    if (n > 3) {
        vector<vector<int>> aa(m, vector<int>(n));
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                aa[j][i] = a[i][j];
            }
        }
        a = aa;
        swap(n, m);
    }

    int rr = INT_MAX;

    for (int e = 0; e <= 1; e++) {
        vector<int> changed_top(m);
        for (int i = 0; i < m; i++) {
            changed_top[i] = ((a[0][i] + a[1][i] + e) & 1) != (i & 1);
        }

        for (int change = 0; change <= 1; change++) {
            for (int change_inf = 0; change_inf <= 1; change_inf++) {
//            cout << e << " " << change << endl;

                int res = accumulate(changed_top.begin(), changed_top.end(), 0);

                if (n > 2) {
                    vector<int> changed_top_inf(m);
                    changed_top_inf[0] = changed_top[0] & change_inf;
                    vector<int> changed_bottom(m);
                    changed_bottom[0] = change;
                    res += change;

                    for (int i = 1; i < m; i++) {
                        int ok = (a[1][i - 1] + a[1][i] + a[2][i - 1] + a[2][i] + changed_top_inf[i - 1] +
                                  changed_bottom[i - 1]) % 2 == 1;
                        if (changed_top[i]) {
                            if (!ok) {
                                changed_top_inf[i] = 1;
                            }
                        } else {
                            if (!ok) {
                                changed_bottom[i] = 1;
                            }
                        }
                    }

                    res += accumulate(changed_bottom.begin(), changed_bottom.end(), 0);
//                for (int i = 0; i < m; i++) {
//                    cout << changed_top[i] << " ";
//                }
//                cout << endl;
//                for (int i = 0; i < m; i++) {
//                    cout << changed_top_inf[i] << " ";
//                }
//                cout << endl;
//                for (int i = 0; i < m; i++) {
//                    cout << changed_bottom[i] << " ";
//                }
//                cout << endl;
//
//                cout << res << endl;
                }

                rr = min(rr, res);
            }
        }

    }

    cout << rr;

    return 0;
}


#include <iostream>
#include <vector>
#include <list>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <string>
#include <algorithm>
#include <cmath>
#include <bitset>
#include <climits>
#include <iomanip>
#include <set>
#include <numeric>

#define long long long int

using namespace std;

int main() {
    ios::sync_with_stdio(false);

    int n, m; cin >> n >> m;

    vector<vector<int>> a(n, vector<int>(m));

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++)  {
            char c; cin >> c;
            a[i][j] = c == '1';
        }
    }

    if (n > 3 && m > 3) {
        cout << -1 << endl;
        return 0;
    }

    if (n > 3) {
        vector<vector<int>> aa(m, vector<int>(n));
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                aa[j][i] = a[i][j];
            }
        }
        a = aa;
        swap(n, m);
    }

    int rr = INT_MAX;

    for (int e = 0; e <= 1; e++) {
        vector<int> changed_top(m);
        for (int i = 0; i < m; i++) {
            changed_top[i] = ((a[0][i] + a[1][i] + e) & 1) != (i & 1);
        }

        for (int change = 0; change <= 1; change++) {
            for (int change_inf = 0; change_inf <= 1; change_inf++) {
//            cout << e << " " << change << endl;

                int res = accumulate(changed_top.begin(), changed_top.end(), 0);

                if (n > 2) {
                    vector<int> changed_top_inf(m);
                    changed_top_inf[0] = changed_top[0] & change_inf;
                    vector<int> changed_bottom(m);
                    changed_bottom[0] = change;
                    res += change;

                    if (changed_top[0]) {
                        changed_top_inf[0] = change_inf;
                    }

                    if (changed_top_inf[0] && change) continue;

                    for (int i = 1; i < m; i++) {
                        int ok = (a[1][i - 1] + a[1][i] + a[2][i - 1] + a[2][i] + changed_top_inf[i - 1] +
                                  changed_bottom[i - 1]) % 2 == 1;
                        if (changed_top[i]) {
                            if (!ok) {
                                changed_top_inf[i] = 1;
                            }
                        } else {
                            if (!ok) {
                                changed_bottom[i] = 1;
                            }
                        }
                    }

                    res += accumulate(changed_bottom.begin(), changed_bottom.end(), 0);
//                for (int i = 0; i < m; i++) {
//                    cout << changed_top[i] << " ";
//                }
//                cout << endl;
//                for (int i = 0; i < m; i++) {
//                    cout << changed_top_inf[i] << " ";
//                }
//                cout << endl;
//                for (int i = 0; i < m; i++) {
//                    cout << changed_bottom[i] << " ";
//                }
//                cout << endl;
//
//                cout << res << endl;
                }

                rr = min(rr, res);
            }
        }

    }

    cout << rr;

    return 0;
}


#include <iostream>
#include <vector>
#include <list>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <string>
#include <algorithm>
#include <cmath>
#include <bitset>
#include <climits>
#include <iomanip>
#include <set>

#define long long long int

using namespace std;

int main() {
    ios::sync_with_stdio(false);

    int n, m; cin >> n >> m;

    vector<vector<int>> a(n, vector<int>(m));

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++)  {
            char c; cin >> c;
            a[i][j] = c == '1';
        }
    }

    if (n > 3 && m > 3) {
        cout << -1 << endl;
        return 0;
    }

    if (m <= 3 && n > 3) {
        vector<vector<int>> aa(m, vector<int>(n));
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                aa[j][i] = a[i][j];
            }
        }
        a = aa;
        swap(n, m);
    }

    int even_even = 0;
    int even_odd = 0;
    int odd_even = 0;
    int odd_odd = 0;

    for (int i = 0; i < m; i += 2) {
        if (a[0][i] == a[1][i]) {
            even_even++;
        } else {
            even_odd++;
        }
    }
    for (int i = 1; i < m; i += 2) {
        if (a[0][i] == a[1][i]) {
            odd_even++;
        } else {
            odd_odd++;
        }
    }

    if (n == 2) {
        cout << min(even_odd + odd_even, even_even + odd_odd) << endl;
        return 0;
    }

    int rr = INT_MAX;

    for (int e = 0; e <= 1; e++) {
        for (int change = 0; change <= 1; change++) {

            vector<int> changed_top(m);
            vector<int> changed_bottom(m);
            changed_bottom[0] = change;
            int res = e ? (even_even + odd_odd) : (even_odd + odd_even);

            for (int i = 1; i < m; i++) {
                bool curr_changed_top = false;

                if (((a[0][i] + a[1][i] + e) & 1) != (i & 1)) {
                    curr_changed_top = true;
                }

                int ok = (a[1][i - 1] + a[1][i] + a[2][i - 1] + a[2][i] + changed_top[i - 1] + changed_bottom[i - 1]) % 2 != 0;
                if (curr_changed_top) {
                    if (!ok) {
                        changed_top[i] = 1;
                    }
                } else {
                    if (!ok) {
                        changed_bottom[i] = 1;
                        res++;
                    }
                }
            }

            rr = min(rr, res);
        }
    }

    cout << rr;

    return 0;
}


#include <iostream>
#include <vector>
#include <list>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <string>
#include <algorithm>
#include <cmath>
#include <bitset>
#include <climits>
#include <iomanip>
#include <set>
#include <numeric>

#define long long long int

using namespace std;

int main() {
    ios::sync_with_stdio(false);

    int n, m; cin >> n >> m;

    vector<vector<int>> a(n, vector<int>(m));

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++)  {
            char c; cin >> c;
            a[i][j] = c == '1';
        }
    }

    if (n > 3 && m > 3) {
        cout << -1 << endl;
        return 0;
    }

    if (n > 3) {
        vector<vector<int>> aa(m, vector<int>(n));
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                aa[j][i] = a[i][j];
            }
        }
        a = aa;
        swap(n, m);
    }

    int rr = INT_MAX;

    for (int e = 0; e <= 1; e++) {
        for (int change = 0; change <= 1; change++) {
//            cout << e << " " << change << endl;
            vector<int> changed_top(m);
            for (int i = 0; i < m; i++) {
                changed_top[i] = ((a[0][i] + a[1][i] + e) & 1) != (i & 1);
            }

            int res = accumulate(changed_top.begin(), changed_top.end(), 0);

            if (n > 2) {
                vector<int> changed_top_inf(m);
                vector<int> changed_bottom(m);
                changed_bottom[0] = change;
                res += change;

                for (int i = 1; i < m; i++) {
                    int ok = (a[1][i - 1] + a[1][i] + a[2][i - 1] + a[2][i] + changed_top_inf[i - 1] +
                              changed_bottom[i - 1]) % 2 == 1;
                    if (changed_top[i]) {
                        if (!ok) {
                            changed_top_inf[i] = 1;
                        }
                    } else {
                        if (!ok) {
                            changed_bottom[i] = 1;
                            res++;
                        }
                    }
                }

//                for (int i = 0; i < m; i++) {
//                    cout << changed_top[i] << " ";
//                }
//                cout << endl;
//                for (int i = 0; i < m; i++) {
//                    cout << changed_top_inf[i] << " ";
//                }
//                cout << endl;
//                for (int i = 0; i < m; i++) {
//                    cout << changed_bottom[i] << " ";
//                }
//                cout << endl;
//
//                cout << res << endl;
            }

            rr = min(rr, res);
        }
    }

    cout << rr;

    return 0;
}


#include <iostream>
#include <vector>
#include <list>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <string>
#include <algorithm>
#include <cmath>
#include <bitset>
#include <climits>
#include <iomanip>
#include <set>
#include <numeric>

#define long long long int

using namespace std;

int main() {
    ios::sync_with_stdio(false);

    int n, m; cin >> n >> m;

    vector<vector<int>> a(n, vector<int>(m));

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++)  {
            char c; cin >> c;
            a[i][j] = c == '1';
        }
    }

    if (n > 3 && m > 3) {
        cout << -1 << endl;
        return 0;
    }

    if (n < 2 || m < 2) {
        cout << 0 << endl;
        return 0;
    }

    if (n > 3) {
        vector<vector<int>> aa(m, vector<int>(n));
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                aa[j][i] = a[i][j];
            }
        }
        a = aa;
        swap(n, m);
    }

    int rr = INT_MAX;

    for (int e = 0; e <= 1; e++) {
        vector<int> changed_top(m);
        for (int i = 0; i < m; i++) {
            changed_top[i] = ((a[0][i] + a[1][i] + e) & 1) != (i & 1);
        }

        for (int change = 0; change <= 1; change++) {
            for (int change_inf = 0; change_inf <= 1; change_inf++) {

                int res = accumulate(changed_top.begin(), changed_top.end(), 0);

                if (n > 2) {
                    vector<int> changed_top_inf(m);
                    changed_top_inf[0] = changed_top[0] & change_inf;
                    vector<int> changed_bottom(m);
                    changed_bottom[0] = change;

                    for (int i = 1; i < m; i++) {
                        int ok = (a[1][i - 1] + a[1][i] + a[2][i - 1] + a[2][i] + changed_top_inf[i - 1] +
                                  changed_bottom[i - 1]) % 2 == 1;
                        if (changed_top[i]) {
                            if (!ok) {
                                changed_top_inf[i] = 1;
                            }
                        } else {
                            if (!ok) {
                                changed_bottom[i] = 1;
                            }
                        }
                    }

                    res += accumulate(changed_bottom.begin(), changed_bottom.end(), 0);
                }

                rr = min(rr, res);
            }
        }
    }

    cout << rr;

    return 0;
}


#include <iostream>
#include <vector>
#include <list>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <string>
#include <algorithm>
#include <cmath>
#include <bitset>
#include <climits>
#include <iomanip>
#include <set>
#include <numeric>

#define long long long int

using namespace std;

int main() {
    ios::sync_with_stdio(false);

    int n, m; cin >> n >> m;

    vector<vector<int>> a(n, vector<int>(m));

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++)  {
            char c; cin >> c;
            a[i][j] = c == '1';
        }
    }

    if (n > 3 && m > 3) {
        cout << -1 << endl;
        return 0;
    }

    if (n > 3) {
        vector<vector<int>> aa(m, vector<int>(n));
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                aa[j][i] = a[i][j];
            }
        }
        a = aa;
        swap(n, m);
    }

    int rr = INT_MAX;

    for (int e = 0; e <= 1; e++) {
        vector<int> changed_top(m);
        for (int i = 0; i < m; i++) {
            changed_top[i] = ((a[0][i] + a[1][i] + e) & 1) != (i & 1);
        }

        for (int change = 0; change <= 1; change++) {
            for (int change_inf = 0; change_inf <= 1; change_inf++) {

//            cout << e << " " << change << " " << change_inf << endl;

                int res = accumulate(changed_top.begin(), changed_top.end(), 0);

                if (n > 2) {
                    vector<int> changed_top_inf(m);
                    changed_top_inf[0] = changed_top[0] & change_inf;
                    vector<int> changed_bottom(m);
                    changed_bottom[0] = change;

                    for (int i = 1; i < m; i++) {
                        int ok = (a[1][i - 1] + a[1][i] + a[2][i - 1] + a[2][i] + changed_top_inf[i - 1] +
                                  changed_bottom[i - 1]) % 2 == 1;
                        if (changed_top[i]) {
                            if (!ok) {
                                changed_top_inf[i] = 1;
                            }
                        } else {
                            if (!ok) {
                                changed_bottom[i] = 1;
                            }
                        }
                    }

                    res += accumulate(changed_bottom.begin(), changed_bottom.end(), 0);

//                    for (int i = 0; i < m; i++) {
//                        cout << changed_top[i] << " ";
//                    }
//                    cout << endl;
//                    for (int i = 0; i < m; i++) {
//                        cout << changed_top_inf[i] << " ";
//                    }
//                    cout << endl;
//                    for (int i = 0; i < m; i++) {
//                        cout << changed_bottom[i] << " ";
//                    }
//                    cout << endl;
//
//                    cout << res << endl;
                }

                rr = min(rr, res);
            }
        }
    }

    cout << rr;

    return 0;
}