思路:
枚举第一行所有状态,则第二行由第一行灯的状态决定,以此类推。(若要将上一行开着的灯关闭,在下一行只能拨动对应列的开关)
优化:
因第一列的状态数为2**6=64,因此可用一个整数表示所有情况,通过位运算来实现相应位的改变。
代码如下:
#include<iostream> #include<memory> #include<cstring> #include<string> using namespcae std; int GetBit(char c,int i) { //取c的第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 ); } void Flip(char &c,int i) { //将c的第i位取反 c ^= ( 1 << i ); } 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() { char oriLights[5]; //原始的等矩阵 char lights[5]; //寄存矩阵,灯变化的结果存放这里 char result[5]; //结果 char switchs; //表示某一行的灯开关方案 int T; cin>>T; for(int t=1;t<=T;t++) { memset(oriLights,0,sizeof(oriLights)); 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++) { memcpy(lights,oriLights,sizeof(oriLights)); switchs = n; 第1行的开关状态 for(int i=0;i<5;i++) { result[i] = switchs; //第i行的开关方案 for(int j=0;j<6;j++) { if(GetBit(switchs,j)) { if(j>0) Flip(lights[i],j-1); //改左灯 Flip(lights[i],j); if(j<4) Flip(lights[i],j+1); } } if(i<4) lights[i+1] ^= switchs; //改下一行的灯 switchs = lights[i]; //第i+1行的开关方案就是第i行的灯开关状态 } if(ligths[4] == 0) { OutputResult(t,result); break; } } } return 0; }