XMUOJ-校外实训一 【熄灯问题】

 

思路:

按照顺序,若第一行的状态固定,例如“0 1 1 0”,则第二行必须按下第2,3列,而1,4列不能按下,以此类推,只要第一行状态固定,则直至最后一行状态全部固定,所以可以通过讨论第一行的所有状态,从中寻找正确答案。

第一行一共六列,故状态有2^6=64种,枚举64种情况

代码:

#include<iostream>
#include<bitset>
#include<algorithm>
using namespace std;
int main(){
    int x;
    cin>>x;
    bitset<6> source[5],lights[5],res[5],line;
    for(int a=1;a<=x;++a)
    {
        for(int i=0;i<5;++i)
            for(int j=0;j<6;++j)
            {
                int y;
                cin>>y;
                source[i].set(j,y);
            }
        for(int n=0;n<64;n++)                        //第一行的64种情况
        {
            line=n;                                              //以二进制把第一行状态储存在line中
            for(int i=0;i<5;i++)lights[i]=source[i];
            for(int i=0;i<5;++i)
            {
                res[i]=line;                                     //0,1在line中表示灯为暗与亮,在res中表示不按与按
                for(int j=0;j<6;++j)
                {
                    if(line.test(j))                            //检测是否为1,即是否需要按下
                    {
                        if(j>0)lights[i].flip(j-1);             
                        lights[i].flip(j);
                        if(j<5)lights[i].flip(j+1);
                    }
                }
                if(i<4)lights[i+1]^=line;                            //修改下一行灯的状态(^=应该是按位异或操                                                                                     作,我是现查的资料)
                line=lights[i];                                            //  i行灯的亮暗即代表下一行应该如何按
            }
            if(lights[4].none())                                     //若最后一行为0,输出
            {
                cout<<"PUZZLE #"<<a<<endl;
                for(int i=0;i<5;i++)
                {
                    for(int j=0;j<6;j++)
                    {
                        cout<<res[i][j]<<" ";
                    }
                    cout<<endl;
                }
                break;    
            }
        }
        
    }
    
    return 0;
}

^=太巧妙了

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值