北京大学 程序设计与算法(二)枚举 熄灯问题

#include<bits/stdc++.h>
using namespace std;
char oriLights[5]; //存下一个矩阵的状态
char lights[5]; //存下变化的灯的矩阵
char result[5]; //存下结果
int GetBit(char c,int i)
{return (c>>i)&1;} //取出一个状态的一位。将字符c右移i位,跟1进行与操作。
void SetBit(char &c,int i,int v) //将c的第i位变成v
 { if(v){c|=(1<<i);} //如果v是1,c或等于1左移i
else
c&= ~(1<<i); //c与等于1左移i位取反
}
void FlipBit(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(){
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){
    int switchs = n;  //从全不按开始枚举每一种按开关的情况
    memcpy(lights,oriLights,sizeof(oriLights)); //将原始数据复制到lights中去操作
    for(int i=0;i<5;++i){
        result[i]=switchs;
        for(int j=0;j<6;j++){
            if(GetBit(switchs,j)/* 如果第j位是1,那么要按下开关*/){
                if(j>0)//如果j不是在最左边一列的
                    FlipBit(lights[i],j-1);
                FlipBit(lights[i],j);
                if(j<5)
                    FlipBit(lights[i],j+1);
            }
        }
        if(i<4)//处理对下一行的影响
            lights[i+1]^=switchs;//一个比特跟1异或就会被反转,跟0异或就不会
        switchs = lights[i]; //switchs是i+1行的按开关的状态。往下开始下一行的循环
    }
    if(lights[4]==0){
        OutputResult(t,result);
        break;
    }
}
}
}

猜你喜欢

转载自www.cnblogs.com/Invictus-Gaming/p/12244502.html