https://ac.nowcoder.com/acm/problem/235250
思路:将每一行的数据看成一个二进制串,可以发现如果想要达成相同的颜色,由第一行的操作可以确定接下来所有行的操作,因此我们可以枚举第一行所有可能的操作,由于 m 比较小,外层循环只需要枚举 2^m -1,时间不会爆。在具体操作时采用二进制,用 a 数组和 b 数组将两个相反的棋盘存入,这样只需将两个数组跑同一个函数即可。
#include<bits/stdc++.h>
#define endl '\n'
#define pii pair<int,int>
using namespace std;
const int maxn = 10+3;
int n,m;
int a[maxn],b[maxn];
int change[maxn];
int transform(int x)
{
int ans=0;
while(x)
{
if(x&1)
{
ans++;
}
x>>=1;
}
return ans;
}
int cal(string s,bool sig)
{
int ans=0;
int len=s.length();
for(int i=0;i<len;i++)
{
if(sig)
ans |= (s[i]-'0')<<(len-i-1);
else
ans |= (!(s[i]-'0'))<<(len-i-1);
}
return ans;
}
int deal(int a[])
{
int ans=0x7f7f7f;
int cur[maxn],cnt=0; // 新开一个数组临时存储每个change[0]修改后的状态
for(change[1]=0;change[1]<=(1<<m)-1;change[1]++)
{
cnt=transform(change[1]);
// change 修改正对着的格子,左边的格子,右边的格子
cur[1]=a[1]^change[1]^(change[1]>>1)^((change[1]<<1)&((1<<m)-1));
// 修改 change 对应的下一行的格子
cur[2]=a[2]^change[1];
for(int i=2;i<=n;i++)
{
cnt+=transform(change[i]);
change[i]=cur[i-1]; // 当前行怎么按
cur[i]=cur[i]^change[i]^(change[i]>>1)^((change[i]<<1)&((1<<m)-1));
cur[i+1]=a[i+1]^change[i];
}
if(cur[n]==0)
{
ans=min(ans,cnt);
}
}
return ans;
}
void solve()
{
cin>>n>>m;
string s;
for(int i=1;i<=n;i++)
{
cin>>s;
a[i]=cal(s,1);
b[i]=cal(s,0);
}
int ans=min(deal(a),deal(b));
cout<<ans<<endl;
}
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int T; T=1;
while(T--) solve();
return 0;
}