AC代码如下:(利用的是位运算)
#include <cstdio>
#include <cstring>
#include<iostream>
using namespace std;
char oriLights[5];
char light[5];
char result[5];
int getbit(char c,int i)//取出字节
{
return(c>>i)&1;
}
void setbit(char & c,int i,int v)//
{
if(v)//v=1
{
c|=(1<<i);//或运算符 v等于1 c与1左移i位进行或运算 就是把这个
//位改变成1;并且其他位与0进行或 是不变的
}
else
{
c&=~(1<<i);// v=0 1左移i位与c进行 与 运算 就是把这个位改变成1
//并且其他位都与1进行与 是不变的
}
}
void flipbit(char & c,int i)//翻转 函数
{
c^=(1<<i);//与1左移i位进行异或 若是1则变为0 0则变为1
//其他位与0进行异或 若是0则0 若是1则1 就是不变!
}
void outputresult(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 t=1;t<=T;t++)
{
for(int i=0;i<5;i++)//两重循环 输入每一盏灯
{
for(int j=0;j<6;j++)
{
int s;//就是输入的灯
cin>>s;
setbit(oriLights[i],j,s);
}
}
for(int n=0;n<64;++n)//用0-63 二进制作为解决方案 遍历所有情况 因为2^6转化
{
int switchs=n;//表示当前行的开关状态
memcpy(light,oriLights,sizeof(oriLights));
//每次假设一个解决方案//开关方案出现后
//都要把orilight复制到light中 以后的操作都在light中进行
for(int i=0;i<5;++i)//五次循环 5层的解决方案
{
result[i]=switchs;//把每一行的开关状态存在resulti中
//第i行的开关状态应该是已经确定的
//i等于0的时候就是 n
//i不等于0时就是 利用上一层的灯 若亮着则是1 我们要把它灭掉
//下一行肯定会在1下面关灯 关灯的指令又刚好是1 所有直接利用上一层的灯亮情况就是下一层的result!
for(int j=0;j<6;j++)//检查第i行的每个灯
{
if(getbit(switchs,j))//把switch的j位字节拿出来
//只有开关被摁下 才需要处理
{
if(j>0)//要影响到j自己 j-1 j+1 所以j-1 j+1必须存在
{
flipbit(lights[i],j-1); //翻转状态
}
flipbit(lights[i],j);//翻转状态
if(j<5) //翻转状态
{
flipbit(lights[i],j+1);
}
}
}
if(i<5)//处理i+1行灯的情况
{
lights[i+1]^=switchs; //switch代表第i行灯的开关状态
//若switch.j=1 即开关按下 则与1异或 就应该翻转
//若switch.j=0 即开关按下 则与0异或 不变 保持原状
}
switchs=lights[i];
}
if(light[4]==0)//如果最后一层全灭了灯 就说明成功的方案 就输出
{
outputresult(t,result);
break;
}
}
}
return 0;
}