以二进制枚举第一排的翻转法,第一排确定后,第二排,第三排。。。的翻转就已经确定了,最后到最后一排看是否全部翻转
#include<iostream>
#include<algorithm>
#include<string>
#include<queue>
#include<cmath>
#include<vector>
#include<stdlib.h>
#include<iomanip>
#include<list>
#include<stack>
#include<memory.h>
#include<ctype.h>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
const int maxn = 20;
const int dx[] = { -1,0,0,0,1 };
const int dy[] = { 0,-1,0,1,0 };
int chess[maxn][maxn];
int m, n;
int opt[maxn][maxn];
int filp[maxn][maxn];
int get(int x, int y) {
int c = chess[x][y];
for (int i = 0; i < 5; i++) {
int x2 = x + dx[i];
int y2 = y + dy[i];
if (0 <= x2&&x2 < m && 0 <= y2&&y2 < n) {
c += filp[x2][y2];
}
}
return c % 2;
}
int cal() {
for (int i = 1; i < m; i++) {
for (int j = 0; j < n; j++) {
if (get(i - 1, j) != 0) {
filp[i][j] = 1;
}
}
}
for (int j = 0; j < n; j++) {
if (get(m - 1, j) != 0)return -1;
}
int ans = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
ans += filp[i][j];
}
}
return ans;
}
void solve() {
int ans = -1;
for (int i = 0; i < 1 << n; i++) {
memset(filp, 0, sizeof(filp));
for (int j = 0; j < n; j++) {
filp[0][n - j - 1] = i >> j & 1;
}
int num = cal();
if (num >= 0 && (ans<0 || ans>num)) {
ans = num;
memcpy(opt, filp, sizeof(filp));//
}
}
if (ans < 0) {
printf("IMPOSSIBLE\n");
}
else {
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
printf("%d%c", opt[i][j], j + 1 == n ? '\n' : ' ');
}
}
}
}
int main() {
cin >> m >> n;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
scanf("%d", &chess[i][j]);
}
}
solve();
}