终于有时间自己写一遍了,然后本菜鸡昨天一整夜都在debug……多亏XHL发现了我的数组越界……太艰难了

思路:穷举第一行,因为完成了一行的操作以后,要关掉第一行的灯,只能从第二行下手,也就是说,第二行的操作和第一行的状态相同,依此类推。最后检查最后一行,如果关好了,就退出穷举循环,输出结果。

菜鸡代码:

#include <iostream>
#include <cstring>
using namespace std;
int a[5][6],b[5][6],ans[5][6];
void SwapLight(int i,int j) {
    a[i][j]=!a[i][j];//自己
    if(i) a[i-1][j]=!a[i-1][j];//上
    if(j) a[i][j-1]=!a[i][j-1];//左
    if(i!=4) a[i+1][j]=!a[i+1][j];//下
    if(j!=5) a[i][j+1]=!a[i][j+1];//右
}
void SwapLine(int line) {
    for(int i=0; i<6; i++)
        if(ans[line][i])SwapLight(line,i);
}
bool Check() {//只需要检查最后一行
    for(int j=0; j<6; j++)
        if(a[4][j])return 0;
    return 1;
}
void Geta(int k) {//获取第一行的操作
    for(int i=0; i<6; i++) {
        ans[0][i]=(k>>i)&1;
    }
}
void Solve() {//优化穷举
    for(int k=0; k<64; k++) {
        memcpy(a,b,sizeof(b));
        memset(ans,0,sizeof(ans));
        Geta(k);
        for(int i=1; i<5; i++) {
            SwapLine(i-1);
            for(int j=0; j<6; j++) {
                if(a[i-1][j]) ans[i][j]=1;
            }
        }
        SwapLine(4);
        if(Check()) return;
    }
    cout<<"ERROR"<<endl;
}
int main() {
    int t;
    cin>>t;
    for(int PU=1; PU<=t; PU++) {
        for(int i=0; i<5; i++)
            for(int j=0; j<6; j++)
                cin>>b[i][j];
        Solve();
        cout<<"PUZZLE #"<<PU<<endl;
        for(int i=0; i<5; i++) {
            for(int j=0; j<6; j++) {
                cout<<ans[i][j];
                if(j!=5)cout<<" ";
            }
            cout<<endl;
        }
    }
    return 0;
}

郭炜老师的代码:

#include <cstring>
#include <iostream>
using namespace std;
int GetBit(int c,int i) {//取c的第i位
    return  ( c >> i ) & 1;
}
void SetBit(int & c,int i, int v) {//设置c的第i位为v
    if( v )  c |= ( 1 << i);//如果v==1 或 
    else c &= ~( 1 << i);//置零 
}
void Flip(int & c, int i) {//将c的第i位为取反
    c ^= ( 1 << i);
    //1^0=1 0^0=0 A^0=A
    //A^1=!A
    //c ^= ( 1 << i); 这种写法可以对一个数操作 可以理解为一个二进制字串 
}
void OutputResult(int t,int 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 oriLights[5];//最初灯矩阵,一个比特表示一盏灯
    int lights[5];    //不停变化的灯矩阵
    int result[5];    //结果开关矩阵
    int 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 ) {    //遍历首行开关的64种状态
            memcpy(lights,oriLights,sizeof(oriLights));
            switchs = n;//第i行的开关状态
            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 < 5 ) Flip(lights[i],j+1);//改右灯
                    }
                }
                if( i < 4 ) lights[i+1] ^= switchs;//改下一行的灯
                switchs = lights[i]; //第i+1行开关方案和第i行灯情况同
            }
            if( lights[4] == 0 ) {
                OutputResult(t,result);
                break;
            }
        }
    }
    return 0;
}

再次吐槽牛客网不适合写博客 我明明排好版了,因为tab所占字符数设置不一样又乱了,还不如笔记软件……