
一、核心思路
对于每组测试数据,通过二进制枚举第一行的所有可能状态并判断其是否合法,根据偶数矩阵的性质来依次递推后面行的最终状态,同时判断其是否合法,若合法并统计改变元素的次数。
二、代码实现
cpp
int T;
const int N = 20;
int a[N], b[N], n;
// 判断是否合法,并且计算0->1变化的次数
int exam(int x, int y)
{
int sum = 0;
for (int i = 0; i < n; i++)
{
int m = (x >> i) & 1;
int n = (y >> i) & 1;
if (m == 1 && n == 0) return -1;
if (m == 0 && n == 1) sum++;
}
return sum;
}
int solve()
{
int ret = 0x3f3f3f3f;
//枚举第一行的最终状态
for (int i = 0; i < (1 << n); i++)
{
// 备份初始数组
memcpy(b, a, sizeof a);
int change = i;
int cnt = 0;
bool flag = 1;
for (int j = 1; j <= n; j++)
{
// 检查该行的合法性
int tmp = exam(b[j], change);
if (tmp == -1)
{
flag = 0;
break;
}
else cnt += tmp;
// 更新当前行的状态
b[j] = change;
// 下一行的状态
change = (b[j] << 1) ^ (b[j] >> 1) ^ b[j-1];
change &= ((1 << n) - 1); // 消除干扰
}
if(flag) ret = min(ret, cnt);
}
if (ret == 0x3f3f3f3f) return -1;
else return ret;
}
int main ()
{
cin >> T;
for (int t = 1; t <= T; t++)
{
// 多组数据,进行初始化
memset(a, 0, sizeof a);
cin >> n;
// 存储初始数据
for(int i = 1; i <= n; i++)
{
for (int j = 0; j < n; j++)
{
int x; cin >> x;
a[i] |= (x << j);
}
}
cout << "Case " << t << ": " << solve() << endl;
}
return 0;
}