算法流程
- 枚举第一行的修改情况
change[0]
。
- 每一行修改后的结果,即为该行的输入
input[i]
与change[i]
、change[i >> 1]
、change[i << 1] & ((1 << M) - 1)
的^
异或运算结果,这里注意,在进行change[i << 1]
左移运算时,要跟(1 << M) - 1
进行&
运算的原因是,只保留后M
位的运算结果,其他全部需要清零,以避免影响最终结果。
- 每一行的修改情况,即为上一行在修改后留下的结果,
change[i] = cur[i - 1]
,因为只有当前行可以将上一行为1的位进行翻转。
- 最后判断是否已经达到全0(只需判断最后一行即可,因为此时
cur[1]~cur[N-1]
全为0)。
代码
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 4, M = 4;
int a[N + 10], b[N + 10];
int change[N + 10];
int calc(int x)
{
int cnt = 0;
while (x)
{
if (x & 1)
cnt++;
x >>= 1;
}
return cnt;
}
int deal(int a[])
{
int cur[N + 10], cnt = 0, ans = 0x7f7f7f7f;
for (change[0] = 0; change[0] <= (1 << M) - 1; change[0]++)
{
cnt = calc(change[0]);
cur[0] = a[0] ^ change[0] ^ (change[0] >> 1) ^ ((change[0] << 1) & ((1 << M) - 1));
cur[1] = a[1] ^ change[0];
for (int i = 1; i < N; i++)
{
change[i] = cur[i - 1];
cnt += calc(change[i]);
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 - 1] == 0)
{
ans = min(ans, cnt);
}
}
return ans;
}
int main()
{
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
{
char c;
scanf(" %c", &c);
if (c == 'b')
a[i] |= (1 << j);
else
b[i] |= (1 << j);
}
int ans = min(deal(a), deal(b));
if (ans > N * M)
cout << "Impossible";
else
cout << ans;
return 0;
}