1222:EXTENDED LIGHTS OUT
The aim of the game is, starting from any initial set of lights on in the display, to press buttons to get the display to a state where all lights are off. When adjacent buttons are pressed, the action of one button can undo the effect of another. For instance, in the display below, pressing buttons marked X in the left display results in the right display.Note that the buttons in row 2 column 3 and row 2 column 5 both change the state of the button in row 2 column 4,so that, in the end, its state is unchanged.
Note:
1. It does not matter what order the buttons are pressed.
2. If a button is pressed a second time, it exactly cancels the effect of the first press, so no button ever need be pressed more than once.
3. As illustrated in the second diagram, all the lights in the first row may be turned off, by pressing the corresponding buttons in the second row. By repeating this process in each row, all the lights in the first
four rows may be turned out. Similarly, by pressing buttons in columns 2, 3 ?, all lights in the first 5 columns may be turned off.
Write a program to solve the puzzle.
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 0 1 0 0 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
在矩阵角上的按钮改变3盏灯的状态
在矩阵边上的按钮改变4盏灯的状态
其他的按钮改变5盏灯的状态
对矩阵中的每盏灯设置一个初始状态。请你按按钮,直至每一盏等都熄灭。与一盏灯毗邻的多个按钮被按下时,一个操作会抵消另一次操作的结果。在下图中,第2行第3、5列的按钮都被按下,因此第2行、第4列的灯的状态就不改变
第2次按下同一个按钮时,将抵消第1次按下时所产生的结果。因此,每个按钮最多只需要按下一次。
各个按钮被按下的顺序对最终的结果没有影响
对第1行中每盏点亮的灯,按下第2行对应的按钮,就可以熄灭第1行的全部灯。如此重复下去,可以熄灭第1、2、3、4行的全部灯。同样,按下第2、3、4、5、6列的按钮,可以熄灭前5列的灯。
此时要熄灭第1行某个亮着的灯(假设位于第i列),那么唯一的办法就是按下第2行第i列的开关(因为第一行的开关已经用过了,而第3行及其后的开关不会影响到第1行)。
第2行的开关起作用后,为了熄灭第二行的灯,第3行的合理开关状态就也是唯一的,以此类推,最后一行的开关状态也是唯一的。
因此,只需枚举第一行的状态,状态数是2的6次方= 64
a[i][j]=1:灯(i, j)初始时是被点亮的
a[i][j]=0:灯(i, j)初始时是熄灭的
用一个矩阵b[5][6]表示要计算的结果
b[i][j]=1:需要按下按钮(i, j)
b[i][j]=0:不需要按下按钮(i, j)
有下列等式成立(0<i<5, 0<j<6)
a[i][j]=(b[i][j-1]+b[i][j]+b[i][j+1]+ b[i-1][j]+b[i+1][j]) % 2
b[5][6]共有2的30次方种可能取值
在每种取值情况下,看看是否找到答案;若找到,则返回;若没有,则尝试下一种取值的情况
问题1:如何进行枚举?如果每行开关数目是N那怎么办?
第二个函数deal():对b的第一行的给定取值,根据熄灯规则计算出b的其他行的值,判断这个b能否使得矩阵第五行的所有灯也恰好熄灭。
第0行、第0列和第7列不属于b矩阵范围,可全置0
b[r+1][c]=(a[r][c]+b[r][c-1]+b[r][c]+b[r][c+1] + b[r-1][c])% 2
0<r<5, 0<c<7
#include<cstdio> using namespace std ; int a[6][8] ;//表示灯的初始状态 int b[6][8] ;//表示要计算的结果 /** 对a的第一行的给定取值, 根据熄灯规则计算出a的其他行的值, 判断这个a能否使得矩阵第五行的所有灯也恰好熄灭。 */ bool deal() { int c,r ; for(r=1;r<5;r++) for(c=1;c<7;c++) b[r+1][c]=(a[r][c]+b[r][c]+b[r][c-1]+b[r][c+1]+b[r-1][c])%2 ; for(c=1;c<7;c++) if((b[5][c-1]+b[5][c]+b[5][c+1]+b[4][c])%2!=a[5][c]) return false ; return true ; } void temp() { int c ; for(c=1;c<7;c++) b[1][c] = 0 ; while(deal()==false){ b[1][1]++; c=1 ; while(b[1][c]>1){ b[1][c] = 0 ; c++ ; b[1][c]++ ; } } return ; } int main() { int cases,i,r,c ; scanf("%d",&cases) ; for(r=0;r<6;r++) b[r][0] = b[r][7] = 0;//把第0列和第7列全部置0 for(c=1;c<7;c++) b[0][c] = 0 ; for(i=0;i<cases;i++){ for(r=1;r<6;r++)//行 for(c=1;c<7;c++)//列 scanf("%d",&a[r][c]); temp(); printf("PUZZLE #%d\n", i+1); for(r=1;r<6;r++){ for(c=1;c<7;c++) printf("%d ",b[r][c]); printf("\n"); } } return 0 ; }
相关推荐
Bipartite number 的定义是形如 a...ab...b 的数字,例如 1222、333999999 等。 **数据规模:** - 给定整数 x 的范围:x 。 **解题思路:** 1. **特殊情况处理:** - 当 x 为 10 的倍数时,n 必须也是 10 的倍数...
7.4.2 枚举 152 7.4.3 控件接口 152 7.4.4 TOleControl的派生类 152 7.4.5 方法 152 7.4.6 属性 153 7.5 在应用程序中使用ActiveX控件 153 7.6 发布带有ActiveX控件的应用程序 154 7.7 注册ActiveX控件 155 7.8 ...