一个由按钮组成的矩阵,其中每行有6个按钮,共5行。每个按钮的位置上有一盏灯。当按下一个按钮后,该按钮以及周围位置(上边、下边、左边、右边)的灯都会改变一次。即,如果灯原来是点亮的,就会被熄灭;如果灯原来是熄灭的,则会被点亮。在矩阵角上的按钮改变3盏灯的状态;在矩阵边上的按钮改变4盏灯的状态;其他的按钮改变5盏灯的状态。
所以在5x6的矩阵中,左边矩阵中用X标记的按钮表示被按下,右边的矩阵表示灯状态的改变。对矩阵中的每盏灯设置一个初始状态。请你按按钮,直至每一盏等都熄灭。与一盏灯毗邻的多个按钮被按下时,一个操作会抵消另一次操作的结果。在下图中,第2行第3、5列的按钮都被按下,因此第2行、第4列的灯的状态就不改变。
所以在5x6的矩阵中,左边矩阵中用X标记的按钮表示被按下,右边的矩阵表示灯状态的改变。对矩阵中的每盏灯设置一个初始状态。请你按按钮,直至每一盏等都熄灭。与一盏灯毗邻的多个按钮被按下时,一个操作会抵消另一次操作的结果。在下图中,第2行第3、5列的按钮都被按下,因此第2行、第4列的灯的状态就不改变。
请你写一个程序,确定需要按下哪些按钮,恰好使得所有的灯都熄灭
样例输入:
2
0 1 1 0 1 0
1 0 0 1 1 1
0 0 1 0 0 1
1 0 0 1 0 1
0 1 1 1 0 0
0 0 1 0 1 0
1 0 1 0 1 1
0 0 1 0 1 1
1 0 1 1 0 0
0 1 0 1 0 0
样例输出:
PUZZLE #1
1 0 1 0 0 1
1 1 0 1 0 1
0 0 1 0 1 1
1 0 0 1 0 0
PUZZLE #2
1 0 0 1 1 1
1 1 0 0 0 0
0 0 0 1 0 0
1 1 0 1 0 1
1 0 1 1 0 1
思路:用第二行灭第一行,一次类推,判断最后一行是否灭
#include<stdio.h>
//#include<stdlib.h>
int puzzle[6][8],press[6][8];//定义多1行2列数组方便判断,就不要特指第一行和两边的列为特殊情况
bool guess(){
int c,r;
for(r=1;r<5;r++)//当第一行按下的按钮确定时候,其他几行按钮也能确定了
for(c=1;c<7;c++)
{
press[r+1][c]=(puzzle[r][c]+press[r][c]+press[r-1][c]+press[r][c-1]+press[r][c+1])%2;
}
for(c=1;c<7;c++){
if((press[5][c-1]+press[5][c]+press[5][c+1]+press[4][c])%2!=puzzle[5][c])//判断,假如puzzle为1,如果press
return false; //也为1,则能熄灭,同为0也能熄灭
} //所以判断他们是否相等判断第五行
return true;
}
void enumerate()
{
int c,i;
for(c=1;c<7;c++)
press[1][c]=0;
while(guess()==false)//列举第一行所以次数,用二进制法列举
{
press[1][1]++; //低位不断加1
c=1;
while(press[1][c]>1) //前面两行代码执行了两次,大于1了,才执行此程序
{
press[1][c]=0; //进了位,要减1
c++;
press[1][c]++; //c++执行后,向前进一位
}
}
return;
}
int main()
{
int i,j,c,k;
int cases;
for(i=0;i<6;i++)
puzzle[i][0]=puzzle[i][7]=press[i][0]=press[i][7]=0;//当等于0时并不能影响模2的结果
for(c=1;c<7;c++)
puzzle[0][c]=press[0][c]=0;
scanf("%d",&cases);
while(cases--){
for(i=1;i<6;i++){
for(j=1;j<7;j++){
scanf("%d",&puzzle[i][j]);
}
}
enumerate();
k=1;
printf("Puzzle#%d\n",k);
k++;
for(i=1;i<6;i++){
for(j=1;j<7;j++){
printf("%d ",press[i][j]);
}
printf("\n");
}
}
return 0;
}