题目地址:http://contest-hunter.org:83/contest/0x00「基本算法」例题/0201 费解的开关
求灯全亮,我开始求了全灭。 读题很重要, 哭哭
每一个灯可以由以及其上下左右五盏灯来影响。每个位置至多只会被点击一次,点击的顺序不影响最终结果。
我们先用二进制枚举暴力假定第一行的点击情况,把第一行固定好,若发现第一行存在灯灭,只能通过点击第二行的灯会处理(第一行的点击情况已固定)。
处理完,再看第二行是否存在灯灭,若存在只能通过点击第三行处理,因为你若点击第二行,会造成第一行有灯灭(第一行的灯已经全亮了);依次类推,到第五行;点击完成后,看是否灯全亮,找出灯全亮的最小步数。
#include <iostream>
#include <cstdio>
#include<stdlib.h>
using namespace std;
#define INF 0x3fffff
char s[15][12];
int a[15][15],b[15][15];
void chuli(int x,int y)
{
b[x][y]=(b[x][y]+1)%2;
b[x][y+1]=(b[x][y+1]+1)%2;
b[x][y-1]=(b[x][y-1]+1)%2;
b[x-1][y]=(b[x-1][y]+1)%2;
b[x+1][y]=(b[x+1][y]+1)%2;
}
bool judge()
{
for(int i=1; i<=5; i++)
for(int j=1; j<=5; j++)
{
if(!b[i][j])
return false;
}
return true;
}
void swap1()
{
for(int i=1;i<=5;i++)
for(int j=1;j<=5;j++)
{
b[i][j]=a[i][j];
}
}
void printf1()
{
for(int i=1;i<=5;i++)
{
for(int j=1;j<=5;j++)
{
printf("%d",b[i][j]);
}
printf("\n");
}
}
int main()
{
int n;
int ans,sum;
ans=26;
scanf("%d",&n);
while(n--)
{
ans=26;
for(int i=1; i<=5; i++)
scanf("%s",s[i]);
for(int i=1; i<=5; i++)
{
for(int j=0; j<5; j++)
{
a[i][j+1]=s[i][j]-'0';
}
}
/// swap1();
///printf1();
for(int i=0;i<(1<<5);i++)
{
swap1();
sum=0;
for(int j=0;j<5;j++)
{
if((i>>j)&1)
{
chuli(1,j+1);
sum++;
}
}
for(int j=1;j<5;j++)
{
for(int k=1;k<=5;k++)
{
if(!b[j][k])
{
chuli(j+1,k);
sum++;
}
}
}
if(judge())
ans=min(ans,sum);
}
if(ans>6)
printf("-1\n");
else
printf("%d\n",ans);
}
return 0;
}