二进制搜索 开关问题
第一次碰到利用二进制表示状态的题目,利用二进制每一位上的0或1代表黑白。思路来自网上的一些大佬。
#include<cstdio>
#include<cstring>
using namespace std;
int a[20][20], tmp[20][20], ans[20][20], res, n, m;
int next[][2] = {-1,0,0,1,1,0,0,-1,0,0};
int get(int x,int y) //判断是否需要翻转
{
int c = a[x][y];
for(int i = 0; i < 5; i++){
int tx = x + next[i][0];
int ty = y + next[i][1];
if(tx > 0 && tx <= n && ty > 0 && ty <= m) c += tmp[tx][ty];
}
return c%2;
}
int calc()
{
for(int i = 2; i <= n; i++){
for(int j = 1; j <= m; j++){
if(get(i-1,j)) tmp[i][j] = 1;
}
}
for(int i = 1; i <= m; i++){ //判断最后一行是否全部为0
if(get(n,i)) return -1;
}
int res = 0;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
res += tmp[i][j];
}
}
return res;
}
void solve()
{
res = -1;
for(int i = 0; i < (1<<m); i++){ //枚举状态,从全0到全1
memset(tmp,0,sizeof(tmp));
for(int j = 1; j <= m; j++){ //记录此时第一行的状态
tmp[1][m-j+1] = (i>>(j-1))&1;
}
int num = calc();
if(num >= 0 && (res < 0 || res > num)){
res = num;
memcpy(ans,tmp,sizeof(tmp));
}
}
}
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]);
}
}
solve();
if(res < 0) printf("IMPOSSIBLE\n");
else{
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
printf("%d ",ans[i][j]);
}
printf("\n");
}
}
return 0;
}