题目描述
你玩过“拉灯”游戏吗?25盏灯排成一个5x5的方形。每一个灯都有一个开关,游戏者可以改变它的状态。每一步,游戏者可以改变某一个灯的状态。游戏者改变一个灯的状态会产生连锁反应:和这个灯上下左右相邻的灯也要相应地改变其状态。
我们用数字“1”表示一盏开着的灯,用数字“0”表示关着的灯。下面这种状态
10111
01101
10111
10000
11011
在改变了最左上角的灯的状态后将变成:
01111
11101
10111
10000
11011
再改变它正中间的灯后状态将变成:
01111
11001
11001
10100
11011
给定一些游戏的初始状态,编写程序判断游戏者是否可能在6步以内使所有的灯都变亮。
输入格式
第一行输入正整数n
,代表数据中共有n
个待解决的游戏初始状态。
以下若干行数据分为n
组,每组数据有5行,每行5个字符。每组数据描述了一个游戏的初始状态。各组数据间用一个空行分隔。
输出格式
一共输出n
行数据,每行有一个小于等于6的整数,它表示对于输入数据中对应的游戏状态最少需要几步才能使所有灯变亮。
对于某一个游戏初始状态,若6步以内无法使所有灯变亮,则输出“-1”。
数据范围
0<n≤500
样例
输入样例:
3
00111
01011
10001
11010
11100
11101
11101
11110
11111
11111
01111
11111
11111
11111
11111
输出样例:
3
2
-1
算法1
#include <bits/stdc++.h>
using namespace std;
char a[10][10],b[10][10];
int dx[5]={0,0,0,-1,1},dy[5]={0,1,-1,0,0};//中,上,下,左,右 五个方向
void turn(int x,int y){
for (int i = 0; i < 5; ++i) {
int b=x+dx[i];int c=y+dy[i];
if(b>=0&&b<5&&c>=0&&c<5){
a[b][c]^=1;//是0就改为1,是1就改为0
}
}
}
int work(){
int as=1000000000;//把as设成尽可能大的数
for (int k = 0; k < (1<<5); ++k) { //枚举第一行的操作操作操作,1就代表我按了,0代表我没按
//要求最短步数,所以第一行按法要一个一个的枚举找最短步数,这里一行5个灯,用二进制来表示,5位的二进制数 00000~11111 0~31 例如5=00101,表示按下了第一行的第3个灯和第5个灯,k>>j&1判断j位是否为1,也就是是否按下此灯,为1就是按下此灯
memcpy(b,a,sizeof(a));
//把a复制到b,等第一行的这一种按法用完之后再恢复回来成原来的二维数组进行下一种第一行的按法
int ans=0;
int is_successful=1;
for (int j = 0; j < 5; ++j) {
if(k>>j&1){
ans++;
turn(0,j);
}
}
for (int i = 0; i < 4 ; ++i) {//看前四行就行了,最后一行无法改变了
for (int j = 0; j < 5; ++j) {
if(a[i][j]=='0'){//如果它是灭的,我就按它下面的灯
ans++;
turn(i+1,j);
}
}
}
for (int j = 0; j < 5; ++j) {//看最后一行是否还有灭的灯,有的话就不成立,没有把所有灯变亮
if(a[4][j]=='0'){
is_successful=0;
break;
}
}
if(is_successful) as=min(ans,as);
memcpy(a,b,sizeof(b));//恢复
}
if(as>6) return -1;
return as;
}
int main()
{
int n;
cin>>n;//几组数据
while(n--){
for (int i = 0; i < 5; ++i) {
cin>>a[i];//输入的是一个字符串
}
cout<<work()<<endl;
}
return 0;
}
算法
#include <bits/stdc++.h>
using namespace std;
int a[7][7],b[7][7],n,answer;
int init()
{
getchar();
for (int i=1;i<=5;i++)
{
for (int j=1;j<=5;j++)
{
char ch=getchar();
a[i][j]=ch-'0';
}
getchar();
}
}
int handle(int x,int y)
{
b[x][y]^=1;
b[x-1][y]^=1;
b[x][y+1]^=1;
b[x][y-1]^=1;
b[x+1][y]^=1;
}
bool judge(void)
{
for (int i=1;i<=5;i++)
for (int j=1;j<=5;j++)
if(!b[i][j])
return false;
return true;
}
int work(void)
{
answer=1e7;
for (int i=1;i<=(1<<5);i++)
{
int ans=0;
memcpy(b,a,sizeof(a));
for (int j=1;j<=5;j++)
if (i>>(j-1) & 1)
{
handle(1,j);
ans++;
}
for (int j=1;j<=4;j++)
for (int k=1;k<=5;k++)
if (!b[j][k])
{
ans++;
handle(j+1,k);
}
if (judge())
answer=min(ans,answer);
}
return answer;
}
int main()
{
cin>>n;
while(n--)
{
init();
if (work()<=6)
cout<<answer;
else
cout<<"-1";
puts("");
}
return 0;
}