poj1222

题目传送门
题目描述:
有一个由按钮组成的矩阵,其中每行有6个按钮,共五行
每个按钮位置上有一盏灯
当按下一个按钮后,该按钮以及周围位置(上边,下边,左边,,右边)灯都会改变状态
如果灯原来是点亮的,就会被熄灭
如果灯原来是熄灭的,就会被点亮

  • 在矩阵角上的按钮会改变三盏灯的状态
  • 在矩阵边上的灯会改变4盏灯的状态
  • 其他的按钮改变五盏灯的状态
    与一盏灯毗邻的多个按钮被按下时,一个操作会抵消另一个操作的结果
    给定每盏灯的初始状态,求一种按钮方案,使得所有的灯都熄灭
    如果要枚举所有的情况有2^30种,这是不可能的。所以还要寻找一些规律:

当第一行的switchs已经确定了,操作之后:
that means,只要第一行确定怎么按,其他行都是确定的。

               如果位置(1, j)上的灯是点亮的,则要按下位置(2, j)上按钮,即Lights[2][j]一定取1;
               如果位置(1, j)上的灯是熄灭的,则不能按位置(2, j)上按钮,即Lights[2][j]一定取0。

这样依据Lights的第一、二行操作矩阵中的按钮,才能保证第一行的灯全部熄灭。依此类推,可以确定switchs第三 四 五 行的值。
所以具体实现方法就是:先枚举出switchs第一行的所有情况,总共有2^6=64种。再根据 上面的规律确定switchs第三 四 五 行的值。最后判断第五行的灯是否全部熄灭,若全部熄灭则找到了答案。 代码实现如下:
这题主要是学会了关于二进制数的位运算

#include<iostream>
#include<stdio.h>
#include<string>
#include<memory>
#include<cstring>
using namespace 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=0; 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++)
        {
            switchs=n;
            memcpy(Lights,oriLights,sizeof(oriLights));
            for(int i=0; i<5; i++)
            {
                result[i]=switchs;
                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];
            }
        if(Lights[4]==0)
        {
            OutputResult(t+1,result);
            break;
        }
        }//n 0-64 的那个循环
    }
return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值