题目链接:UVA 11464
题意:给定一个01矩阵,size:n * n,0可以变成1,1不可以转为0让你求出最小的变化数满足它成为一个偶数矩阵(任一点上下左右(存在)之和为偶数);
题解:这题如果枚举所有01有2^255的复杂度。显然不行,
可以降低枚举层次,只枚举第一层,然后根据偶数矩阵的特征递推,满足条件返回,不满足退出;
ps:因为是01矩阵,枚举第一层的状态,比如
让第一层达到0~2^n-1的状态,如果不能直接退出,可以的话 递推
AC code:
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn = 15 + 5;
#define debug 0
#define inf 0x3f3f3f3f
int n, m;
int a[maxn][maxn],b[maxn][maxn];
int Do(int c) {
memset(b, 0, sizeof(b));
for (int i = 0; i < n; i++) { //让第一层各元素组成的二进制可以表示c,比如 c=5 ,n=8
//此时让第一层转成10100000
if (c & (1 << i)) { //因为 0 -> 1可行,所以当前位一定可以转成
b[0][i] = 1;
}
else {
if (a[0][i] == 1) //如果c二进制当前为0,但是原数组当前元素为1,返回inf
return inf;
}
}
for(int i = 1; i < n; i++) //通过b[i - 1][j]找b[i][j]
for (int j = 0; j < n; j++) {
int sum = 0;
if(i > 1)
{
sum += b[i - 2][j];
}
if (j > 0)
sum += b[i - 1][j - 1];
if (j < n - 1)
sum += b[i - 1][j + 1];
b[i][j] = sum % 2;
if (a[i][j] == 1 && b[i][j] == 0) //返回
return inf;
}
int ans = 0;
for(int i = 0; i < n; i++)
for (int j = 0; j < n; j++) {
if (a[i][j] != b[i][j])
ans++; //找变化数
}
return ans;
}
int main() {
#if debug
freopen("in.txt", "r", stdin);
#endif//debug
int t;
scanf("%d", &t);
for (int kase = 1; kase <= t; kase++) {
scanf("%d", &n);
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
scanf("%d", &a[i][j]);
int ans = inf;
for (int i = 0; i < (1 << n); i++) {
ans = min(ans, Do(i));
}
if (ans == inf)
ans = -1;
printf("Case %d: %d\n", kase, ans);
}
return 0;
}