//二进制枚举
//遇到的问题就是在判断某点当前状态时,感觉可以不考虑当前位置的翻转,毕竟不会存在翻了一次又翻一次的状况....但是 当取消这一情况,就会WA。。。。后来发现是第一行初始化的时候,flip会取1.....所以....就需要考虑自身是否翻转了...
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 15+5;
const int inf = 0x3f3f3f3f;
int n, m;//n行m列
int Map[N][N];//存储原始数据
int flip[N][N];//存储翻转数据
int fin[N][N];//最终的翻转数据
int ans = inf; //翻转最少次数
int dir[5][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}, {0, 0}};//上下左右
int Judge(int x, int y)//此时的状态与==之前的状态以及之前的上下左右及自己的翻转状态有关
{
int tmp = Map[x][y];
for(int i=0; i<5; i++){
int tx = x+dir[i][0];
int ty = y+dir[i][1];
if(tx>=1 && tx<=n && ty>=1 && ty<=m){
tmp += flip[tx][ty];
}
}
return tmp&1;
}
void Search()
{
for(int i=2; i<=n; i++){
for(int j=1; j<=m; j++){
if(Judge(i-1, j)){//上一层有黑色的
flip[i][j] = 1;
}
}
}
for(int i=1; i<=m; i++){
if(Judge(n, i)){//第n行仍有黑色的
return;
}
}
int tmp = 0;
for(int i=1; i<=n; i++){
for(int j=1; j<=m; j++){
if(flip[i][j]){
tmp++;
}
}
}
if(tmp<ans && tmp){
ans = tmp;
memcpy(fin, flip, sizeof(flip));
}
}
int main()
{
cin >> n >> m;
for(int i=1; i<=n; i++){
for(int j=1; j<=m; j++){
cin >> Map[i][j];
}
}
for(int i=0; i<(1<<m); i++){//枚举第一行的2^m状态,即取和不取
memset(flip, 0, sizeof(flip));
for(int j=1; j<=m; j++){
flip[1][j] = (i >> (j-1))&1;//将第一行的状态映射到flip的第一行中
}
Search();
}
// cout << ans;
if(ans == inf){
cout << "IMPOSSIBLE" << endl;
}
else
for(int i=1; i<=n; i++){
for(int j=1; j<=m; j++){
cout << fin[i][j] << " ";
}
cout << endl;
}
return 0;
}

本文介绍了一种使用二进制枚举的方法来解决特定的翻转棋盘问题。通过枚举棋盘第一行的所有可能状态,并递归地确定后续行的状态,以找出达到全白状态所需的最小翻转次数。
171

被折叠的 条评论
为什么被折叠?



