在一个5*5的01矩阵中,点击任意一个位置,该位置以及它上、下、左、右四个相邻位置中的数字都会变化(0变成1,1变成0),求最少需要多少次点击可以把一个给定的01矩阵变成全1矩阵?
题解:枚举第一行的点击方法,共32种,对于每种情况,固定第一行,若第一行中有0,唯一的解决方案就是点击对应得第二行的数字,递推后可以发现固定第一行以后点击方案是确定的,那么枚举32种情况计算最小值即可。
#include<iostream>
#include<vector>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
int n,ans,ant;
int a[5][5],b[5][5];
char str[6];
void change(int x,int y){
b[x][y]=b[x][y]^1;
if(x-1>=0) b[x-1][y]=b[x-1][y]^1;
if(x+1<5) b[x+1][y]=b[x+1][y]^1;
if(y-1>=0) b[x][y-1]=b[x][y-1]^1;
if(y+1<5) b[x][y+1]=b[x][y+1]^1;
}
int main(){
cin>>n;
while(n--){
ans=7;
for(int i=0;i<5;i++){
cin>>str;
for(int j=0;j<5;j++){
if(str[j]=='0')
a[i][j]=0;
else if(str[j]=='1')
a[i][j]=1;
}
}
for(int k=0;k<=31;k++){
for(int i=0;i<5;i++)
for(int j=0;j<5;j++)
b[i][j]=a[i][j];
ant=0;
for(int j=0;j<5;j++){
if((k>>j)&1){
ant++;
change(0,j);
}
}
for(int i=1;i<5;i++){
for(int j=0;j<5;j++){
if(b[i-1][j]==0){
ant++;
change(i,j);
}
}
}
int kase=1;
for(int i=0;i<5;i++){
for(int j=0;j<5;j++){
if(b[i][j]==0){
kase=0;
break;
}
}
if(kase==0) break;
}
if(kase==1) ans=min(ans,ant);
}
if(ans<=6){
cout<<ans<<endl;
}
else
cout<<-1<<endl;
}
return 0;
}