25盏灯排成一个 5×5的方形。
每一个灯都有一个开关,游戏者可以改变它的状态。
每一步,游戏者可以改变某一个灯的状态。
游戏者改变一个灯的状态会产生连锁反应:和这个灯上下左右相邻的灯也要
相应地改变其状态。
我们用数字 1表示一盏开着的灯,用数字 0表示关着的灯。
给定一些游戏的初始状态,编写程序判断游戏者是否可能在 6步以内使所有的灯都变亮。
输入格式:
第一行输入正整数 n,代表数据中共有 n个待解决的游戏初始状态。
以下若干行数据分为 n组,每组数据有 5行,每行 5个字符。
每组数据描述了一个游戏的初始状态。
各组数据间用一个空行分隔。
输出格式:
一共输出 n行数据,每行有一个小于等于6的整数,
它表示对于输入数据中对应的游戏状态最少需要几步才能使所有灯变亮。
对于某一个游戏初始状态,若 6步以内无法使所有灯变亮,则输出 −1。
数据范围
0<n≤500
#include<bits/stdc++.h>
using namespace std;
//按的顺序无所谓
//1、枚举 只要第一行开关的状态确定,则所有开关的状态都可以被推出来
//只要最后一行没0就合法,否则不合法
const int N=6;//字符串最后有个\0字符,也需要空间
char g[N][N],bg[N][N];//要恢复现场,把数据读到备份数组
int dx[N]={-1,0,1,0,0};
int dy[N]={0,1,0,-1,0};
void turn(int x,int y)//按xy开关
{
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;//异或,不同的时候就变成相反的数
}
}
int main()
{
int T;
cin>>T;
while(T--)
{
//每次操作的时候从备份数组中copy全新数组
for(int i=0;i<5;i++)
{
cin>>g[i];
}
int res=10;//原则上是无穷,但这个题大于6就会输出-1
for(int op=0;op<32;op++) //枚举第一行的所有操作方案,2^5种
{
int cnt=0;//当前这种方案的操作步数
memcpy(bg,g,sizeof g);//从备份数组种把全新数组复制
for(int i=0;i<5;i++)//枚举第一行怎么操作的,枚举每一位是不是1
if(op>>i & 1)
{
turn(0,i);//按第0行的第i个开关
cnt++;
}
for(int i=0;i<4;i++)//从第一行的灯开始看,到倒数第二行
for(int j=0;j<5;j++)//枚举开关
if(g[i][j]=='0') //这个灯是0的话,需要按下边开关
{
turn(i+1,j);
cnt++;
}
//检查最后一行灯是否全亮
bool success=true;
for(int j=0;j<5;j++)
if(g[4][j]=='0')
{
success=false;
break;
}
if(success)
res=min(res,cnt);
memcpy(g,bg,sizeof g);
}
if(res>6)
res=-1;
cout<<res<<endl;
}
return 0;
}