这道题目和费解的开关https://www.cnblogs.com/fx1998/p/12767815.html类似一点点。
解题思路:
一共有16个开关,每个开关可以选择按一下或不按这两种状态。
所以可能的结果一共有2^16=65536,对于每种情况,再遍历一下4*4的矩阵看是否全是打开的,再乘以16,2^16 * 16 = 1,048,576。再加上其他运算所用的时间,总时间复杂度很小,可以直接暴力。
但是费解的开关是5*5,所有可能的情况是2^25=33,554,432,时间复杂度较高,所以不考虑暴力。
所以用一个16位的二进制数字,来表示进行的操作,0表示不按,1表示按。用二进制从0~2^16 - 1,枚举所有的情况。
将4*4棋盘的开关标号为:
0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15
这道题目还可以用二进制来优化,但没必要,暴力可过。
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N = 5; 4 char g[N][N], bk[N][N]; 5 typedef pair<int, int> PII; 6 #define fi first 7 #define se second 8 int get(int x, int y) { 9 return x * 4 + y; 10 } 11 void turn_one(int x, int y) { 12 if (g[x][y] == '+') { 13 g[x][y] = '-'; 14 } else { 15 g[x][y] = '+'; 16 } 17 } 18 void turn_all(int x, int y) { 19 for (int i = 0; i < 4; i++) { 20 turn_one(x, i); 21 turn_one(i, y); 22 } 23 turn_one(x, y); 24 } 25 int main() { 26 for (int i = 0; i < 4; i++) { 27 cin >> g[i]; 28 } 29 vector<PII> res; 30 for (int op = 0; op < (1 << 16); op++) { 31 vector<PII> t; 32 memcpy(bk, g, sizeof g); //备份 33 for (int i = 0; i < 4; i++) { //操作 34 for (int j = 0; j < 4; j++) { 35 if (op >> get(i, j) & 1) { 36 t.push_back(make_pair(i, j)); 37 //t.push_back({i, j}); 38 turn_all(i, j); 39 } 40 } 41 } 42 //判断灯泡是否全亮 43 bool flag = true; 44 for (int i = 0; i < 4; i++) { 45 for (int j = 0; j < 4; j++) { 46 if (g[i][j] == '+') { 47 flag = false; 48 } 49 } 50 } 51 if (flag) { 52 if (res.empty() || res.size() > t.size()) { 53 res = t; 54 } 55 } 56 memcpy(g, bk, sizeof g); //还原 57 } 58 cout << res.size() << endl; 59 for (int i = 0; i < res.size(); i++) { 60 cout << res[i].fi + 1 << " " << res[i].se + 1 << endl; 61 } 62 return 0; 63 }