Acwing-95-费解的开关
链接:
https://www.acwing.com/problem/content/description/97/
题意:
你玩过“拉灯”游戏吗?25盏灯排成一个5x5的方形。每一个灯都有一个开关,游戏者可以改变它的状态。每一步,游戏者可以改变某一个灯的状态。游戏者改变一个灯的状态会产生连锁反应:和这个灯上下左右相邻的灯也要相应地改变其状态。
给定一些游戏的初始状态,编写程序判断游戏者是否可能在6步以内使所有的灯都变亮。
思路:
考虑每一行要根据上一行来改变,枚举第一行的点击情况,挨个向下使全部变成1,如果有解则比较步数,如果无解则继续下一个判断.
代码:
#include <bits/stdc++.h>
using namespace std;
char ori[10][10];
int a[10][10], b[10][10];
int n, m;
void Change(int x, int y)
{
b[x][y] ^= 1;
b[x-1][y] ^= 1;
b[x+1][y] ^= 1;
b[x][y+1] ^= 1;
b[x][y-1] ^= 1;
}
bool Check()
{
for (int i = 1;i <= 5;i++)
{
for (int j = 1;j <= 5;j++)
if (b[i][j] == 0)
return false;
}
return true;
}
int Solve()
{
int res = 1e7;
for (int i = 0;i < (1<<5);i++)
{
int ans = 0;
for (int j = 1;j <= 5;j++)
{
for (int k = 1;k <= 5;k++)
b[j][k] = a[j][k];
}
for (int j = 1;j <= 5;j++)
{
if ((i>>(j-1)) & 1)
{
Change(1, j);
ans++;
}
}
for (int j = 1;j <= 4;j++)
{
for (int k = 1;k <= 5;k++)
{
if (b[j][k] == 0)
{
Change(j+1, k);
ans++;
}
}
}
if (Check())
{
// cout << 1 << ' ' << ans << endl;
res = min(res, ans);
}
}
if (res > 6)
return -1;
else
return res;
}
int main()
{
int t;
scanf("%d", &t);
while (t--)
{
for (int i = 1;i <= 5;i++)
scanf("%s", ori[i]+1);
for (int i = 1;i <= 5;i++)
{
for (int j = 1;j <= 5;j++)
a[i][j] = ori[i][j]-'0';
}
int res = Solve();
if (res != -1)
printf("%d\n", res);
else
printf("-1\n");
}
return 0;
}