枚举算法——熄灯问题
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了枚举算法——熄灯问题相关的知识,希望对你有一定的参考价值。
枚举法练习:
题目:
有 一个由按钮组成的矩阵,其中每行有6个按钮,共5行。每个按钮的位置上有一盏灯。当按下一个按钮后,该按钮以及周围位置(上边、下边、左边、右边)的灯都 会改变一次。即,如果灯原来是点亮的,就会被熄灭;如果灯原来是熄灭的,则会被点亮。在矩阵角上的按钮改变3盏灯的状态;在矩阵边上的按钮改变4盏灯的状 态;其他的按钮改变5盏灯的状态。
在 上图中,左边矩阵中用X标记的按钮表示被按下,右边的矩阵表示灯状态的改变。对矩阵中的每盏灯设置一个初始状态。请你按按钮,直至每一盏等都熄灭。与一盏 灯毗邻的多个按钮被按下时,一个操作会抵消另一次操作的结果。在下图中,第2行第3、5列的按钮都被按下,因此第2行、第4列的灯的状态就不改变。
请 你写一个程序,确定需要按下哪些按钮,恰好使得所有的灯都熄灭。根据上面的规则,我们知道1)第2次按下同一个按钮时,将抵消第1次按下时所产生的结果。 因此,每个按钮最多只需要按下一次;2)各个按钮被按下的顺序对最终的结果没有影响;3)对第1行中每盏点亮的灯,按下第2行对应的按钮,就可以熄灭第1 行的全部灯。如此重复下去,可以熄灭第1、2、3、4行的全部灯。同样,按下第1、2、3、4、5列的按钮,可以熄灭前5列的灯。
输入
第一行是一个正整数N,表示需要解决的案例数。每个案例由5行组成,每一行包括6个数字。这些数字以空格隔开,可以是0或1。0表示灯的初始状态是熄灭的,1表示灯的初始状态是点亮的。
输出
对每个案例,首先输出一行,输出字符串“PUZZLE #m”,其中m是该案例的序号。接着按照该案例的输入格式输出5行,其中的1表示需要把对应的按钮按下,0则表示不需要按对应的按钮。每个数字以一个空格隔开。
样例输入:
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
1 //程序实现 2 #include<iostream> 3 using namespace std; 4 int puzzle[6][8], press[6][8];//puzzle数组表示灯的亮灭状态,1表示亮,0表示灭 5 //press数组表示:“是否需要点亮或熄灭指定位置的灯”,1表示是,0表示否 6 bool guess();//声明guess函数 7 void enumeration();//声明enumeration函数 8 int main() { 9 int n; 10 cin >> n; 11 if (n == 0) 12 cout << "error!" << endl; 13 //该段程序可有可无 14 /* for (int i = 0; i < 6; i++) 15 { 16 press[i][0] = 0; 17 press[i][7] = 0; 18 puzzle[i][0] = 0; 19 } 20 for (int i = 0; i < 8; i++) 21 { 22 press[0][i] = 0; 23 puzzle[0][i] = 0; 24 }*/ 25 for (int i = 0; i < n; i++) 26 { 27 for (int r = 1; r < 6; r++) 28 for (int c = 1; c < 7; c++) 29 { 30 cin >> puzzle[r][c]; 31 } 32 33 //调用函数 34 enumeration(); 35 cout << "PUZZLE#" << i+1 << endl; 36 for (int r = 1; r < 6; r++) 37 { 38 for (int c = 1; c < 7; c++) 39 { 40 cout << press[r][c] << " "; 41 } 42 cout << endl; 43 } 44 } 45 } 46 //判断函数 47 bool guess() 48 { 49 for (int r = 1; r < 5; r++) 50 for (int c = 1; c < 7; c++) 51 press[r + 1][c] = (puzzle[r][c] + press[r][c] + 52 press[r][c + 1] + press[r][c - 1] + press[r - 1][c]) % 2; 53 54 for (int c = 1; c < 7; c++) 55 if (puzzle[5][c] != (press[5][c] + press[5][c + 1] + 56 press[5][c - 1] + press[4][c]) % 2) 57 { 58 return false; 59 } 60 61 return true; 62 } 63 //枚举函数 64 void enumeration() 65 { 66 int c; 67 for ( c = 0; c < c; c++) 68 { 69 press[1][c] = 0; 70 } 71 while (guess() == false) 72 { 73 press[1][1]++; 74 c = 1; 75 while (press[1][c]>1) 76 { 77 press[1][c] = 0; 78 c++; 79 press[1][c]++; 80 } 81 } 82 }
以上是关于枚举算法——熄灯问题的主要内容,如果未能解决你的问题,请参考以下文章