题意
拉灯游戏。我们现在给出一个5*5的矩阵,求出在6步以内完成的最少次数,如果不能在6步以内完成就输出-1。
思路
枚举第一行点击的状态。当第i行的灯需要改变状态时,我们只能点击第i+1行这个点来使它改变,因为前i行是固定的。根据这个性质我们可以模拟点击的地方,最后判断一下有没有还原完成就可以记录一下答案了。
代码
#include<cstdio>
#include<algorithm>
using namespace std;
int t,a[7][7],n,ans;
char c[6];
inline int check(int x)
{
int r=0,a1[7][7];
for (int i=1;i<=5;i++)
for (int j=1;j<=5;j++)
a1[i][j]=a[i][j];
for (int i=1;i<=4;i++)//模拟点击
for (int j=1;j<=5;j++)
{
if (!a1[i][j])
{
a1[i][j]=1;
a1[i+1][j]=1-a1[i+1][j];
a1[i+1][j-1]=1-a1[i+1][j-1];
a1[i+1][j+1]=1-a1[i+1][j+1];
a1[i+2][j]=1-a1[i+2][j];
r++;
}
}
for (int i=1;i<=5;i++)
if (!a1[5][i]) return 2147483647;//没有还原返回一个大值
return x+r;//点击次数加上第一行的点击次数
}
void dfs(int dep,int t)//枚举第一行的点击情况,dep代表第一行的第几个点,t代表点击的次数
{
if (dep>5)
{
ans=min(ans,check(t));//统计答案
return;
}
a[1][dep]=1-a[1][dep];
a[1][dep-1]=1-a[1][dep-1];
a[2][dep]=1-a[2][dep];
a[1][dep+1]=1-a[1][dep+1];//点击就改变了
dfs(dep+1,t+1);//代表点击
a[1][dep]=1-a[1][dep];
a[1][dep-1]=1-a[1][dep-1];
a[2][dep]=1-a[2][dep];
a[1][dep+1]=1-a[1][dep+1];//还原
dfs(dep+1,t);//代表不点
}
int main()
{
scanf("%d",&n);
while (n--)
{
ans=2147483647;
for (int i=1;i<=5;i++)
{
scanf("%s",c+1);
for (int j=1;j<=5;j++)
a[i][j]=c[j]-48;
}
dfs(1,0);
if (ans<7) printf("%d\n",ans);
else printf("-1\n");
}
}