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