题目大意:给定5x5的矩阵,元素全为1或0,判断是否可以在6步以内将所有的0换成1(每改变一次,其相邻位置的元素也要改变)1->0,0->1,如果可以,输出最小步数,否则输出-1
解题思路:对于每1盏灯,其都可以有两种操作,一个是按,一个是不按,所以对于一行元素来说总共有2的5次方次操作,二进制表示范围为00000~11111,我们对第一行元素枚举所有情况,每次将为0的灯点亮,下一行位置就会变暗,我们每次都用下一行来改变上一行的状态(将0变为1),枚举到第五行的时候判断这个时候第五行有没有暗的灯,有则代表不可能将所有的灯变亮,否则则输出最少的步数。
参考代码
#include<bits/stdc++.h>
using namespace std;
const int N=6;//多开一个空间存放'\0'
char g[N][N],backup[N][N];
int dx[5]={-1,0,1,0,0},dy[5]={0,1,0,-1,0};
void turn(int x,int y)
{
for(int i=0;i<5;i++)
{
int a=x+dx[i],b=y+dy[i];
if(a<0||a>=5||b<0||b>=5) continue;
g[a][b]^=1;//异或运算,'0'和'1'只有二进制只有最后不同,同则0,不同则1
}
}
int main()
{
int t;
cin>>t;
while(t--)
{
for(int i=0;i<5;i++) cin>>g[i];
int res=10;
for(int op=0;op<32;op++)
{
memcpy(backup,g,sizeof(g));//备份数组,后面要还原
int step=0;
for(int i=0;i<5;i++)
{
if(op>>i&1)//判断二进制的第i位为1,代表按下开关(人为规定)
{
step++;//每按一次步数+1
turn(0,4-i);
}
}
for(int i=0;i<4;i++)//i从0到4,最后一行特判
{
for(int j=0;j<5;j++)
{
if(g[i][j]=='0')
{
step++;
turn(i+1,j);//用下一行来影响上一行的结果
}
}
}
bool dark=false;//对最后一行特判
for(int i=0;i<5;i++)
{
if(g[4][i]=='0')
{
dark=true;
break;
}
}
if(dark==false) res=min(res,step);//32种方案中最小的那种
memcpy(g,backup,sizeof(g));//恢复g数组
}
if(res>6) res=-1;
cout<<res<<endl;
}
return 0;
}