题目:5行6列灯,按下开关会影响上下左右灯,求如何操作能够将灯完全熄灭?
分析如下:
1.首先我们需要枚举一个个开关下去,看灯的变化情况,但如此枚举导致量太大,故将转化思想,以局部枚举确定整体。
2.我们可以发现,当第一行开关状态确定时,后面也将会确定。举例来看:第一行开关状态确定,那么接下来,第二行开关必须将第一行灯全部熄灭,这样才有可能实现目的,故第二行开关状态也将确定。
3.故此,我们可以枚举第一行开关状态。
4.同时,在储存灯的状态时,我们可以用char类型,因为灯、开关只有2个状态,用0,1表示,那么就可用一个bit位储存,char类型一个字节,8个bit位,完全够用,但其中涉及位运算。
5.然后开关状态可用int类型表示,共2^6方种可能。
#include<iostream>
#include<cstring>
#include<memory>
using namespace std;
char orilights[5];
char lights[5];
char result[5];//结果
int Getbit(char c,int i)
{
return (c>>i) & 1;
}
void setbit(char &c,int i,int v)//设置c中第i位为v当
{
if(v)
{
c|=(1<<i);
}
else
{
c&=~(1<<i);//?c&=(0<<i)
}
}
void flipbit (char &c,int i)//将c的第i位翻转,与一亦或
{
c^=(1<<i);
}
void output(int t,char result[])
{
cout<<"PUZZLE #"<<t<<endl;
for(int i=0;i<5;i++)
{
for(int j=0;j<6;j++)
{
cout<<Getbit(result[i],j);
if(j<5)
cout<<" ";
}
cout<<endl;
}
}
int main()
{
int t;//测试组数
cin>>t;
for(int q=0;q<t;q++)
{
for(int i=0;i<5;i++)//读数
{
for(int j=0;j<6;j++)
{
int s;
cin>>s;
setbit(orilights [i],j,s);
}
}
//枚举
int n;
for(n=0;n<64;n++)
{
int switchs=n;
memcpy(lights,orilights,sizeof(orilights));
for(int i=0;i<5;i++)
{ result[i]=switchs;
for(int j=0;j<6;j++)
{
if(Getbit(switchs,j))
{
flipbit(lights[i],j);
if(j>0)
flipbit(lights[i],j-1);
if(j<5)
flipbit(lights[i],j+1);
}
}
if(i<4)
lights[i+1]^=switchs;
switchs=lights[i];
}
if(lights[4]==0)
{
output(q,result);
break;
}
}
}
}