66 lines
2.4 KiB
C++
66 lines
2.4 KiB
C++
#include <bits/stdc++.h>
|
||
using namespace std;
|
||
const int INF = 0x3f3f3f3f;
|
||
const int N = 6;
|
||
|
||
// char 数组版本
|
||
char g[N][N], bg[N][N]; // 工作的临时数组 和 原始状态数组
|
||
|
||
// 上右下左中
|
||
int dx[] = {-1, 0, 1, 0, 0};
|
||
int dy[] = {0, 1, 0, -1, 0};
|
||
|
||
// 按一下第x行第y列的开关
|
||
void turn(int x, int y) {
|
||
for (int i = 0; i < 5; i++) {
|
||
int tx = x + dx[i], ty = y + dy[i];
|
||
if (tx < 0 || tx >= 5 || ty < 0 || ty >= 5) continue;
|
||
g[tx][ty] ^= 1; //'0':48 '1':49
|
||
// (48)_{10}=(110000)_{2} (49)_{10}=(110001)_{2}
|
||
// 由于48的最后一位是0,而49最后一位是1,所以,异或就可以实现两者之间的切换,真是太神奇了~
|
||
}
|
||
}
|
||
|
||
int main() {
|
||
int T;
|
||
cin >> T;
|
||
while (T--) {
|
||
// 按一行的字符串读取
|
||
for (int i = 0; i < 5; i++) cin >> bg[i]; // 原来的字符状态数组
|
||
|
||
// 预求最小,先设最大
|
||
int res = INF;
|
||
|
||
// 枚举所有可能的操作办法:00000,00001,00010,...,11111,共32种办法
|
||
for (int op = 0; op < (2 << 5); op++) {
|
||
int cnt = 0;
|
||
memcpy(g, bg, sizeof g); // 将原始状态复制出一份放入g数组,开始尝试
|
||
|
||
// 操作办法op,共5位,1代表修改,0代表不改,按二进制由右到左可以枚举出这种操作需要改哪几列
|
||
for (int i = 0; i < 5; i++)
|
||
if (op >> i & 1) {
|
||
turn(0, i); // 你想改就改吧~
|
||
cnt++;
|
||
}
|
||
|
||
// 第二行需要观察第一行,啊~我同位的上一行有一个0!这可是大事,因为我必须补上它,否则就没有人可以补上它了~
|
||
for (int i = 0; i < 4; i++)
|
||
for (int j = 0; j < 5; j++)
|
||
if (g[i][j] == '0') {
|
||
turn(i + 1, j); // i+1行必须按下按钮
|
||
cnt++;
|
||
}
|
||
|
||
// 检查最后一行灯是否全亮.因为如果它还有0存在,就没机会补全了
|
||
bool success = true;
|
||
for (int i = 0; i < 5; i++)
|
||
if (g[4][i] == '0') success = false;
|
||
|
||
if (success) res = min(res, cnt); // 如果成功全亮,那你是多少步呢?
|
||
}
|
||
// 题意要求,大于6次,算失败
|
||
if (res > 6) res = -1;
|
||
cout << res << endl;
|
||
}
|
||
return 0;
|
||
} |