题目链接
活动 - AcWing 本活动组织刷《算法竞赛进阶指南》,系统学习各种编程算法。主要面向有一定编程基础的同学。https://www.acwing.com/problem/content/97/
题解
只要第一行开关的状态确定,则所有开关的状态都可以被推出来。第一行开关总共有种操作方法,可以先二进制枚举出第一行的状态,其它行的状态就可以从上一行推出来。上一行为0,下一行必须得变;上一行为1,下一行必须不变。最终,如果最后一行全为1且步数小于等于6,则可以使所有的灯全变亮,否则不能。
代码
#include <cstdio>
#include <cstring>
using namespace std;
const int N = 6;
char g[N][N], bg[N][N];
int dx[5] = {-1, 0, 1, 0, 0}, dy[5] = {0, 1, 0, -1, 0};
void turn(int x, int y) // 按一下第x行第y列的开关
{
for (int i = 0; i < 5; i++)
{
int a = x + dx[i], b = y + dy[i];
if (a < 0 || a >= 5 || b < 0 || b >= 5) continue;
g[a][b] ^= 1;
}
}
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
for (int i = 0; i < 5; i++) scanf("%s", bg[i]);
int res = 10;
for (int op = 0; op < 32; op++)
{
int cnt = 0;
memcpy(g, bg, sizeof g);
// 操作第一行的开关
for (int i = 0; i < 5; i++)
if (op >> i & 1)
{
turn(0, i);
cnt++;
}
// 递推出第1~4行开关的状态
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) res = -1;
printf("%d\n", res);
}
return 0;
}