题目链接
黑白格,最后是否能全部变成白色的。
每次翻转,会连同当前点的上下左右一起翻转。
这个题和一维的差不多。
先确定第一行的情况,每一行的情况根据上一行的的情况确定。
第一行的情况是有 1<<m 种,一行 m 个元素。
每种情况都用一次。
#include <cstring>
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
#define mem(x,v) memset(x,v,sizeof(x))
const int N = 30;
int a[N][N],f[N][N],g[N][N],n,m;
int calc(){
int ans = 0;
for (int i = 2; i <= n; i++){
for (int j = 1; j <= m; j++)
if ((a[i-1][j]+f[i-1][j]+f[i-1][j+1]+f[i-1][j-1]+f[i-2][j]) % 2 == 1 ) //判断上一个节点是不是黑色的,
f[i][j]= 1;
}
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
ans += f[i][j]; //之前忘记加上第一行了。一直 Wrong。
for (int i = 1; i <= m; i++){
if ((f[n][i] +a[n][i] + f[n][i-1] + f[n][i+1] + f[n-1][i]) % 2 == 1 ) return -1;
}
return ans;
}
int main() {
scanf("%d%d",&n,&m);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
scanf("%d",&a[i][j]);
int t,sum = -1;
for (int i = 0; i < 1 << m; i++){
mem(f,0);
int x = m,y = i;
while(y > 0){
f[1][x--] = y & 1; y /= 2; //字典序输出,所以x要从大到小
}
t = calc();
if (t >= 0 && (t < sum || sum < 0)){ //在这个地方错了半天,还有不需要动的数据。
sum = t;
for (int j = 1; j <= n; j++)
for (int k = 1; k <= m; k++)
g[j][k] = f[j][k];
}
}
if (sum < 0) printf("IMPOSSIBLE\n"); else
for (int i = 1; i <= n; i++) {
for (int j = 1; j < m; j++)
printf("%d ",g[i][j]);
printf("%d\n",g[i][m]);
}
return 0;
}