|
|
#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;
|
|
|
} |