题目描述
25 盏灯排成一个 5×5 的方形。
每一个灯都有一个开关,游戏者可以改变它的状态。
每一步,游戏者可以改变某一个灯的状态。
游戏者改变一个灯的状态会产生连锁反应:和这个灯上下左右相邻的灯也要相应地改变其状态。
我们用数字 1 表示一盏开着的灯,用数字 0 表示关着的灯。
样例
3
00111
01011
10001
11010
11100
11101
11101
11110
11111
11111
01111
11111
11111
11111
11111
输出
3
2
-1
太菜了,太菜了,想了一个晚上,结果还是看了题解才会的。
这道题是一道思维题,乍一看,脑子糊涂了,不知道从哪里下手,实际上它具有一定得技巧性,那就是在第一行。
1、第一行的操作会影响第二行,因为:
如果第一行的操作之后,第一行的第j个位置存在黑灯,那么第二行的第j个位置一定要发生转换,这样才能使得第一行的黑灯变成亮灯;第一行的第j个位置是亮灯,那么第二行的第j个位置不能转换。
同理,第二行的操作会影响第三行,依此类推,这道题的重心就落在第一行了;
2、那么第一行要执行怎样的操作呢?这里咱们可以用枚举,枚举每一种操作;不知道还记不记得二进制,咱们可以用二进制来代表咱们需要的操作;比如说11000,第1列和第2列进行转换,第3,4,5不需要转换,也就是说,二进制5个位置中哪个位置存在1就需要转换。
枚举第一行就可以转化成二进制的五位数的最小值到最大值。(0~2^5)
3、最后一步就是转换了,可以写一个调用函数,参数是灯的位置(x,y),如果方形(x,y)等于0,那么转变为1,扽与1,就转变为0;其他四个位置也是同理
如果没讲清楚,就是我太菜了
最后上代码:
char mp[6][6],cp[6][6];
void turn(int x,int y)
{
if(cp[x][y]==‘0’)cp[x][y]=‘1’;
else cp[x][y]=‘0’;
if(cp[x+1][y]==‘0’)cp[x+1][y]=‘1’;
else cp[x+1][y]=‘0’;
if(cp[x-1][y]==‘0’)cp[x-1][y]=‘1’;
else cp[x-1][y]=‘0’;
if(cp[x][y+1]==‘0’)cp[x][y+1]=‘1’;
else cp[x][y+1]=‘0’;
if(cp[x][y-1]==‘0’)cp[x][y-1]=‘1’;
else cp[x][y-1]=‘0’;
}
int main()
{
int t;
scanf(“%d”,&t);
while(t–)
{
int step=0,ans=1e9,fla=0;
for(int i=1; i<=5; i)
{
for(int j=1; j<=5; j)
{
cin>>mp[i][j];
}
}
for(int op=0; op<=32; op)
{
step=0,fla=0;
memcpy(cp,mp,sizeof(mp));
for(int i=0; i<5; i)
{
if((op>>i)&1)
{
turn(1,i+1);
step;
}
}
for(int i=1; i<=4; i)
{
for(int j=1; j<=5; j)
{
if(cp[i][j]==‘0’)
{
turn(i+1,j);
step;
}
}
}
for(int i=1; i<=5; i)
{
for(int j=1; j<=5; j)
if(cp[i][j]==‘0’)fla=1;
}
if(fla==0)ans=min(ans,step);
}
if(ans>6)ans=-1;
cout<<ans<<endl;
}
return 0;
}