题目通道
解法
先枚举第一行的翻转的所有情况。
再根据第一行的枚举情况,综合,黑板的分布,确定下一行的翻转情况。前提是保证上一行的板块都是白。
接着枚举下一行,直到最后一行为止。
到最后一行时,已经确定了所有翻转情况,已经能确定前n-1行全部是白的,如果这时n行全部是白的,说明这个解是成立的。
AC代码
//#include"pch.h"
//#pragma warning(disable:4996);
#include<iostream>
#include<queue>
#include<cstring>
#include<string>
#include<sstream>
#include<map>
#include<vector>
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<stack>
#include<ctime>
using namespace std;
//#define _CRT_SECURE_NO_DEPRECATE;
//#define _CRT_SECURE_NO_WARNINGS;
#define rep(i,aa,bb) for(register int i=aa;i<=bb;i++)
#define rrep(i,aa,bb) for(register int i=aa;i>=bb;i--)
#define LL long long
#define eps 0.000001
#define inf 0x3f3f3f3f
#define exp 0.000001
#define pai 3.141592654
#define random(x) rand()%(x)
#define lowbit(x) x&(-x)
inline int read()
{
int x = 0, y = 1; char a = getchar(); while (a > '9' || a < '0') { if (a == '-')y = -1; a = getchar(); }
while (a >= '0' && a <= '9') { x = 10 * x + a - '0'; a = getchar(); }return x * y;
}
#define N 17
int f[N][N]; int g[N][N], ans[N][N];
inline bool judge(int n, int m) {
for (int i = 1; i <= m; i++) {
int t = f[n][i] + f[n][i - 1] + f[n][i + 1] + f[n - 1][i] + g[n][i];
if (t & 1)
return 0;
}
return 1;
}
int mmin = inf;
void dfs(int n, int m, int k, int num) {
if (num > mmin)
return;
if (k == n + 1) {
if (judge(n, m) && mmin > num) {
memcpy(ans, f, sizeof(f));
mmin = num;
}
return;
}
int t = 0;
for (int i = 1; i <= m; i++) {
if ((g[k - 1][i] + f[k - 1][i] + f[k - 1][i - 1] + f[k - 1][i + 1] + f[k - 2][i]) & 1) {
f[k][i] = 1;
t++;
}
else
f[k][i] = 0;
}
dfs(n, m, k + 1, num + t);
}
void todfs(int n, int m, int k, int num) {
if (k == m+1 ) {
dfs(n, m, 2, num);
/* rep(i, 1, m)
printf("%d ", f[1][i]);
cout << endl;
*/ return;
}
f[1][k] = 0;
todfs(n, m, k + 1, num);
f[1][k] = 1;
todfs(n, m, k + 1, num + 1);
}
int main()
{
// freopen("1.txt", "r", stdin);
srand((int)time(0));
std::ios::sync_with_stdio(false);
int n, m;
n = read(); m = read();
rep(ai, 1, n) rep(bi, 1, m) {
g[ai][bi] = read();
}
todfs(n, m, 1, 0);
if (mmin == inf )
cout << "IMPOSSIBLE" << endl;
else
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
cout << ans[i][j] << " ";
cout << endl;
}
return 0;
}
这种写法不会使字典序最小
void todfs(int n, int m, int k, int num) {
if (k == m + 1 ) {
dfs(n, m, 2, num);
return;
}
f[1][k] = 1;
todfs(n, m, k + 1, num + 1);
f[1][k] = 0;
todfs(n, m, k + 1, num + 0);
}