给你一个01矩阵,矩阵大小为M x N。(1 <= M , N <= 15)
每次操作选择一个格子,使得该格子与上下左右四个格子的值翻转。
至少多少次操作可以使得矩阵中所有的值变为0?
请输出翻转方案,若没有方案,输出"IMPOSSIBLE” 。
若有多种方案符合题意,请首先输出翻转次数最少的方案;若方案个数仍不唯一,则输出字典序最小的方案。
解题方法
用二进制代表第一行的状态,用第一行的状态一次去判断它下一行按与不按,最后判断最后一行是否全为0即可
#include <iostream>
#include <cstring>
using namespace std;
const int INF=0x3f3f3f3f;
int n,m,minn=INF;
int d[5][2]={0,0,0,1,0,-1,1,0,-1,0};
int q[25][25],w[25][25],l[25][25],s[25][25];
void filp(int a,int b)
{
for(int i=0;i<5;i++){
w[a+d[i][0]][b+d[i][1]] = !w[a+d[i][0]][b+d[i][1]] ;
}
}
void dfs()
{
for(int i=0;i < 1<<m;i++){
int res=0;
bool flag=true;
memset(q,0,sizeof q);
memcpy(w,l,sizeof l);
for(int j=0;j<m;j++){
if(i >> (m-1-j) & 1){
filp(1,j+1);
q[1][j+1]=1;
res++;
}
}
for(int i=1;i<n;i++){
for(int j=1;j<=m;j++){
if(w[i][j]){
filp(i+1,j);
q[i+1][j]=1;
res++;
}
}
}
for(int i=1;i<=m;i++){
if(w[n][i]){
flag = false ;
break;
}
}
if(flag){
if(res<minn){
minn=res;
memcpy(s,q,sizeof q);
}
}
}
if(minn<INF){
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cout << s[i][j] << " ";
}
cout << endl;
}
}
else cout << "IMPOSSIBLE" << endl;
}
int main()
{
cin >> n >> m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin >> l[i][j];
dfs();
return 0;
}