https://www.acwing.com/problem/content/97/
思路:
在上述规则的01矩阵的点击游戏中,很容易发现三个性质:
1.每个位置至多会被点击一次
2.若固定了第一行,则满足题意的点击方案至多只有一种。其原因是:当第i行某一位为1时,若前i行被固定,只等点击第i+1行该位置上的数字才能使第i行的这一位改变状态。
3.点击的先后顺序不影响最终结果。
对第一行的点击方案可以位运算,枚举00000~11111这32中情况,为1的位就是第一行被点击的位。
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include <queue>
using namespace std;
char a[10][10];
int b[10][10];
int c[10][10];
int n;
void click(int x,int y){
b[x][y]^=1;
b[x][y-1]^=1;
b[x][y+1]^=1;
b[x-1][y]^=1;
b[x+1][y]^=1;
return ;
}
bool check(){
for(int i=1;i<=5;i++)
for(int j=1;j<=5;j++)
if(!b[i][j]) return false;
return true;
}
int work(){
int t=1e7;
for(int i=1;i<=(1<<5);i++){
int ans=0;
memcpy(b,c,sizeof(c));
for(int j=0;j<5;j++)
if(i>>(j)&1) {
click(1,j+1);
ans++;
}
for(int j=1;j<=4;j++)
for(int k=1;k<=5;k++)
if(!b[j][k]){
click(j+1,k);
ans++;
}
if(check()){
t=min(ans,t);
}
}
return t;
}
int main()
{
cin>>n;
while (n--){
memset(a,0,sizeof(a)) ;
memset(b,0,sizeof(b)) ;
for(int i=1;i<=5;i++){
cin>>a[i];
}
for(int i=1;i<=5;i++)
for(int j=1;j<=5;j++)
c[i][j]=a[i][j-1]-'0';
int anss=work();
if(anss<=6) cout<<anss<<endl;
else cout<<-1<<endl;
}
}