熄灯问题

题解:
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <cmath> 5 #include <cstring> 6 #include <vector> 7 #include <map> 8 #include <stack> 9 #include <queue> 10 #include <deque> 11 #include <list> 12 #include <set> 13 #include <cctype> 14 #include <bitset> 15 16 using namespace std; 17 18 bitset<6> start[5], result[5]; 19 bool turnoff(); // 关灯操作 20 int main() 21 { 22 int t; 23 int num = 1; // 第几组 24 cin >> t; 25 while (t--) 26 { 27 for (int i = 0; i < 5; ++i) 28 { 29 for (int j = 0; j < 6; ++j) 30 { 31 int temp; 32 cin >> temp; 33 start[i][j] = temp; 34 } 35 } 36 37 // 利用二进制枚举第一行64种状态 2^6 38 // 只要确定第一行,则后面也随之确定 39 for (int x = 0; x < 64; ++x) 40 { 41 result[0] = x; // result第一行会自动转化为二进制形态 42 if (turnoff()) 43 break; 44 } 45 46 // 输出结果 47 cout << "PUZZLE #" << num << endl; 48 for (int i = 0; i < 5; ++i) 49 { 50 for (int j = 0; j < 6; ++j) 51 { 52 cout << result[i][j] << " "; 53 } 54 cout << endl; 55 } 56 ++num; 57 } 58 59 return 0; 60 } 61 62 // 执行熄灭操作 63 bool turnoff() 64 { 65 bitset<6> temp[5]; 66 for (int i = 0; i < 5; ++i) 67 temp[i] = start[i]; 68 // 用temp记录灯阵初始状态 69 70 for (int i = 0; i < 5; ++i) 71 { 72 // 根据result的第i行对temp的第i行进行操作 73 for (int j = 0; j < 6; ++j) 74 { 75 // 为1时按下 76 if (result[i][j] == 1) 77 { 78 temp[i].flip(j); // temp的第i行j列取反 79 // 竖直方向 80 if (i != 4) // 若不是最后一行 81 temp[i + 1].flip(j); 82 if (i != 0) // 若不是第一行 83 temp[i - 1].flip(j); 84 // 水平方向 85 if (j != 0) 86 temp[i].flip(j - 1); 87 if (j != 5) 88 temp[i].flip(j + 1); 89 } 90 } 91 // 从temp的第i行判断下一行哪些需要按下 92 if (i < 4) 93 { 94 for (int j = 0; j < 6; ++j) 95 { 96 if (temp[i][j]) 97 result[i + 1][j] = 1; 98 else 99 result[i + 1][j] = 0; 100 } 101 } 102 // 第5行时判断是否全熄灭 103 else 104 for (int j = 0; j < 6; ++j) 105 if (temp[4][j] == 1) 106 return 0; 107 } 108 return 1; 109 }
python代码:
1 def turnoff(start, result): 2 temp = start.copy() # 用来临时储存原灯阵start 3 for i in range(5): 4 for j in range(6): 5 if result[i] & (1 << j): # 如果result[i]的第j位数字为1(按下了),则改变其他按钮状态 6 temp[i] ^= (1 << j) 7 # 下面是边界条件判断 8 if i != 4: 9 temp[i+1] ^= (1 << j) 10 if i != 0: 11 temp[i-1] ^= (1 << j) 12 if j != 0: 13 temp[i] ^= (1 << j - 1) 14 if j != 5: 15 temp[i] ^= (1 << j + 1) 16 if i < 4: # 不是最后一行 17 result[i+1] = temp[i] 18 # 以temp的上一行表示 result的下一行是否按下,例如 19 # 1 0 1 1 0 1 20 # 0 0 0 0 0 0 21 # 0 0 0 0 0 0 22 # 0 0 0 0 0 0 23 # 0 0 0 0 0 0 24 # 第一行若为1,则要按下第二行对应列的按钮 25 else: 26 if temp[4] != 0: # 若最后一行没有全部熄灭,则该方法无法熄灭全部 27 return False 28 return True 29 30 31 t = int(input()) 32 num = 1 33 for _ in range(t): 34 start = [] 35 for _ in range(5): 36 row = int(''.join(input().split()), 2) 37 # 将输入的二进制字符串转换为二进制整数,中间不间隔 38 39 start.append(row) # start中每个元素表示了 **一行灯的状态(是否亮着)**(用一个二进制数表示),5个表示五行 40 result = [0] * 5 # result中每个元素表示了 **一行灯的状态(是否按下)**(用一个二进制数表示),5个表示五行 41 for x in range(64): # 枚举第一行的64种状态(2^6)(因为第一行状态若确定了,则后面的状态也随之确定) 42 result[0] = x 43 if turnoff(start, result): 44 break 45 print('PUZZLE #{}'.format(num)) 46 for i in range(5): 47 row_str = bin(result[i])[2:].zfill(6) # 二进制数格式如 0b1011,则应该舍去前两位0b 48 # 将整数转换为二进制字符串,并在左边补齐0,使其总长度为6 49 50 row = ' '.join(str(x) for x in row_str) 51 print(row, end=' ') # 注意数字末尾有空格 52 print() 53 num += 1

浙公网安备 33010602011771号