You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

66 lines
2.4 KiB

2 years ago
#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;
}