相关描述均在注释里面
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 6;
char g[N][N], bg[N][N];
int T;
//dx[5],dy[5], 简写可是少写几行代码
//这些可以通过一个for循环枚举出要改变的5个灯
int dx[5] = {-1, 0, 1, 0, 0}, dy[5] = {0, 1, 0, -1, 0};
void turn(int x, int y)
{
for (int i = 0; i < 5; i ++ )
{
int nx = x + dx[i], ny = y + dy[i];
if (nx < 0 || nx >= 5 || ny < 0 || ny >= 5) continue;
g[nx][ny] ^= 1;
//字符'0' = 48,'1' = 49, 二进制最后一位不同
//异或一下(相同为0, 不同为1)
}
}
int main()
{
cin >> T;//T次操作
while (T -- )
{
for (int i = 0; i < 5; i ++ )
scanf("%s", bg[i]);//每次复制给g
int res = 10;//大于6次即可
//二进制表示枚举第一行操作,32二进制为10000,正好5位
for (int op = 0; op < 32; op ++ )
{
//memcpy(“”新文档, “原文档”, sizeof “新文档”)
memcpy(g, bg, sizeof g);
int cnt = 0;//统计变灯次数
for (int i = 0; i < 5; i ++ )
if (op >> i & 1)//判断第i个灯是否需要改变
{
turn(0, i);
cnt ++;//次数++
}
//枚举前四行,靠改变下一行来改变
for (int i = 0; i < 4; i ++ )
for (int j = 0; j < 5; j ++ )
if (g[i][j] == '0')
{
turn(i + 1, j);//通过改变它下一行来影响它
cnt ++ ;//次数++
}
bool success = true;//判断是否成功
for (int i = 0; i < 5; i ++ )
if (g[4][i] == '0')
success = false;
//若最后以后有没亮的,则没有下一行来改变它了,
//也不能通过上一行来改变,上一行都是亮的,
//也不能通过旁边的灯来改变它
//因为通过旁边的灯它会改变上一行已经亮灯的状态
//若有更小的答案,选更小的答案
if (success && res > cnt) res = cnt;
}
if (res > 6) cout << -1 << endl;
else cout << res << endl;
}
}