Codeforces #663 div.2 D
題目
A binary matrix is called good if every even length square sub-matrix has an odd number of ones.
Given a binary matrix a consisting of n rows and m columns, determine the minimum number of cells you need to change to make it good, or report that there is no way to make it good at all.
All the terms above have their usual meanings — refer to the Notes section for their formal definitions.
Input
The first line of input contains two integers n and m (1≤n≤m≤106 and n⋅m≤106) — the number of rows and columns in a, respectively.
The following n lines each contain m characters, each of which is one of 0 and 1. If the j-th character on the i-th line is 1, then ai,j=1. Similarly, if the j-th character on the i-th line is 0, then ai,j=0.
Output
Output the minimum number of cells you need to change to make a good, or output −1 if it's not possible at all.
Examples
inputCopy
3 3
101
001
110
outputCopy
2
inputCopy
7 15
000100001010010
100111010110001
101101111100100
010000111111010
111010010100001
000011001111101
111111011010011
outputCopy
-1
思路
顯然當n和m有一個為1或兩者都大於4那麼都不成立(前者為0),那麼資料範圍就被壓縮到了2到3之間,因為很小,所以我們可以預處理出來合法的相鄰兩列的狀態,然後狀態dp去列舉,做法類似於炮兵陣地。
程式碼實現
#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
#define rep(i,f_start,f_end) for (int i=f_start;i<=f_end;++i)
#define per(i,n,a) for (int i=n;i>=a;i--)
#define MT(x,i) memset(x,i,sizeof(x) )
#define rev(i,start,end) for (int i=start;i<end;i++)
#define inf 0x7f7f7f7f
#define mp(x,y) make_pair(x,y)
#define lowbit(x) (x&-x)
#define MOD 1000000007
#define exp 1e-8
#define N 1000005
#define fi first
#define se second
#define pb push_back
typedef long long ll;
typedef pair<int ,int> PII;
ll gcd (ll a,ll b) {return b?gcd (b,a%b):a; }
const int maxn=1000005;
int n,m;
int ans=inf,dp[maxn][8],a[4][maxn];
bool st[8][8]={false};
const int mod=1e9+7;
int calc (int x) {
int ans=0;
while (x) {
if (x&1) ans++;
x>>=1;
}
return ans;
}
int main () {
// freopen ("data.in","r",stdin);
cin>>n>>m;
if (n>=4&&m>=4) {
cout<<"-1"<<endl;
return 0;
}
if (n==1||m==1) {
cout<<0<<endl;
return 0;
}
rep (i,1,n)
rep (j,1,m) scanf ("%1d",&a[i][j]);
rev (i,0,8)
rev (j,0,8) {
int t[3];
t[0]=t[1]=t[2]=0;
rev (p,0,n) {
if ((1<<p)&i) t[p]++;
if ((1<<p)&j) t[p]++;
}
bool flag=1;
rev (p,0,n-1) {
if (!((t[p]+t[p+1])&1)) flag=0;
}
if (flag) st[i][j]=1;
}
MT (dp,0x7f7f7f7f);
rev (i,0,8) dp[0][i]=0;
rep (i,1,m) {
int now=a[1][i]+a[2][i]*2+a[3][i]*4;
rev (j,0,8) {
rev (p,0,8) {
if (!st[j][p]) continue;
dp[i][j]=min (dp[i][j],dp[i-1][p]+calc (now^j));
}
}
}
rev (i,0,8) ans=min (ans,dp[m][i]);
printf ("%d\n",ans);
// fclose (stdin);
return 0;
}