熄灯问题详解

【熄灯问题】:有一个由按钮组成的矩阵, 其中每行有6个按钮, 共5行(C++) 描述: - 有一个由按钮组成的矩阵, 其中每行有6个按钮, 共5行 - 每个按钮的位置上有一盏灯 - 当按下一个按钮后, 该按钮以及周围位置(上边, 下边, 左 边, 右边)的灯都会改变状态 阅读详情

 

 

 

 

输入

2
0 1 1 0 1 0
1 0 0 1 1 1
0 0 1 0 0 1
1 0 0 1 0 1
0 1 1 1 0 0 

0 0 1 0 1 0
1 0 1 0 1 1
0 0 1 0 1 1
1 0 1 1 0 0
0 1 0 1 0 0

输出

PUZZLE #1
1 0 1 0 0 1
1 1 0 1 0 1
0 0 1 0 1 1
1 0 0 1 0 0
0 1 0 0 0 0

PUZZLE #2
1 0 0 1 1 1
1 1 0 0 0 0
0 0 0 1 0 0
1 1 0 1 0 1
1 0 1 1 0 1

以上就是熄灯问题的内容,接下来我们来分析

一、分析问题

1、简单分析

由各个按钮对灯的影响可知:

a、一个按钮最多只需要按一次

b、按下按钮的顺序对结果不会有影响

2、深入分析

通过按钮的影响以及灯的排列方式,我们可以简单的给出两个办法:

a、

暴力法,枚举,2 的 30 次方 是很大的一个数,如此的话这个程序对时间与空间的使用都是极大的,所以不使用这个方法(因为特别容易超时)

b、

第2个方法是,在第 i 行 的灯可以由  第 i + 1 行的按钮来熄灭 (i<5)

比如,第 1 行的 灯的状态是                                                                                                                                                                      0 1 0 1 1 0   

那么我们第 2 行的按钮就根据第一行的灯的状态来操作,即 第 2 行的按钮的操作为                                                                                0 1 0 1 1 0                                                                                   (1为按下按钮,0不按下按钮)(注意!!!就是说第 i+1 行的操作结果等于 第 i 行的灯的状态!记住且理解这个!待会要考)(如果无法理解接受可以自己在草稿纸上演练一遍,前面有例子)(最好自己在草稿纸上演练一遍加以理解)

这样第 1 行的灯就全熄灭了,然后第 2 行的灯接着由第 3 行的按钮来熄灭

但是问题来了,最后一行的灯如何熄灭?

我们只有5行的灯,前面 4 行都由它们的 i+1 行来熄灭,而第 5 行却没有它的 i+1 行帮它熄灭,所以第 5 行,也就是最后一行只能靠自己,也就是说 第 5 行不仅要熄灭第 4 行的灯,同时还要在熄灭第 4 行的灯的同时,也要恰好能熄灭自己第 5 行的灯

为了第 5 行的灯能恰好熄灭,所以我们就要枚举第 1 行的灯在进行了怎样的操作之后,能够在后续 i+1 行的操作下,使第 5 行的灯能恰好熄灭

比如,我第 1 行的操作是 0 0 0 0 0 0 的情况下,后续操作能够使最后一行灯恰好熄灭(即不操作最后一行也能熄灭)

或者如果不行,那么枚举下一种情况,即我第 1 行的操作是 0 0 0 0 0 1 的情况下,后续操作能够使最后一行灯恰好熄灭(即我按了一次第 1 行第 6 列的那妞,然后最后一行恰好熄灭)

如果不行则继续枚举下去

枚举的长度为 2的6次方  64     可以接受,不容易超时

分析完毕,接下来,我们开始设计算法

二、设计算法

1、输入值的保存

对于灯的状态值的保存我们直接就能想到用整型数组来保存,

但是我们再看一下输入样例和输出样例,它们的数值都只涉及到 1、0,就是说在整个运算过程中我们的运算只需要能处理 1、0 即二进制运算即可  

二进制对应的计算也就是位运算,为了方便位运算,所以我们不用整型数组保存,而采用 char 类型数组来保存

因为 char 类型由一个字节8位长度,所以保存一行6个灯的状态的存储空间就足够了

(先记住这个,如何保存我们一会儿再说。因为这个不是算法的核心,然后忘了位运算的话可以百度一下,很容易就想起来的)

2、写下完整代码

#include<iostream>
#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) // 这个函数主要用于保存输入的灯的状态
{
    if( v )
        c |= 1<<i;
    else
        c &= ~(1<<i);
}

void Filp(char & c,int i)  //  这个函数用于反转灯的状态  即 0 变 1 ,1 变 0
{
    c ^= 1<<i;
}

void OutputResult(char result[],int t) //输出结果
{
    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 n;
    cin>>n;
    for(int t=1; t<=n; ++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 i=0; i<64; ++i)  // 用来枚举结果
        {
            switchs = i;  // 这是第 1 行的操作
            memcpy(lights,oriLights,sizeof(oriLights)); // 不使用strcpy的原因是 str是字符串的拷贝,mem是字节拷贝,无限制数据类型  str总会拷贝‘\0’,有溢出风险
            for(int j=0; j<5; j++) // 遍历每一行
            {
                result[j] = switchs;  // 将操作结果保存
                for(int k=0; k<6; k++)  // 遍历每一位
                {
                    if( getBit(switchs,k)){  // 返回为 1 则需要操作,即改变所影响到的灯的状态
                        if(k>0)             // 改左边
                            Filp(lights[j],k-1);
                        Filp(lights[j],k); // 改自己
                        if(k<5)
                            Filp(lights[j],k+1);   //  改右边
                    }
                }
                if(j<4) // 改下一行的收到操作影响的灯的状态
                    lights[j+1] ^= switchs;
                switchs = lights[j];  // 考点: i 行的灯的状态等于 i+1 行的操作
            }

            if(lights[4] == 0)  判断最后一行的灯的状态是否是全部熄灭
            {
                OutputResult(result,t);
                break;
            }
        }
    } // for(int k=0; k<n; ++k)

    return 0;
}

大致就是如此了,如有不懂,可评论

NOI 2.1.1813 熄灯问题 题解(C++) NOI 2.1.1813 熄灯问题 题解 不废话了,直接上题。 题目 1813:熄灯问题 总Time Limit: 1000ms Memory Limit: 65536kB Description 有一个由按钮组成的矩阵,其中每行有6个按钮,共5行。每个按钮的位置上有一盏灯。当按下一个按钮后,该按钮以及周围位置(上边、下边、左边、右边)的灯都会改变一次。即,如果灯原来是点亮的,就会被熄灭;如果灯原... 阅读详情

相关推荐

熄灯问题-枚举(局部思想法解题,采用二维数组或位运算)

OpenJudge-NOI/2.1基本算法之枚举-1813:熄灯问题 总时间限制: 1000ms 内存限制: 65536kB 描述 有一个由按钮组成的矩阵,其中每行有6个按钮,共5行。每个按钮的位置上有一盏灯。当按下一个按钮后,该按钮以及周围位置(上边、下边、左边、右边)的灯都会改变一次。即,如果灯原来是点亮的,就会被熄灭;如果灯原来是熄灭的,则会被点亮。在矩阵角上的按钮改变3盏灯的状态;在矩阵边上的按钮改变4盏灯的状态;其他的按钮改变5盏灯的状态。 在上图中,左边矩阵中用X标记的按钮表示被按下,右边

年少挽滑稽世无双的博客 2736

【算法-枚举】熄灯问题 通俗详细的解题叙述(OpenJudege-2811)

对于该问题的描述: https://www.bilibili.com/video/av10046345/?p=4 #p4熄灯问题 http://bailian.openjudge.cn/practice/2811/ #OpenJudege-2811

Monster的博客 4315

熄灯问题详解(技巧枚举)

有一个由按钮组成的矩阵,其中每行有6个按钮,共5行。每个按钮的位置上有一盏灯。当按下一个按钮后,该按钮以及周围位置(上边、下边、左边、右边)的灯都会改变一次。即,如果灯原来是点亮的,就会被熄灭;如果灯原来是熄灭的,则会被点亮。在矩阵角上的按钮改变3盏灯的状态;在矩阵边上的按钮改变4盏灯的状态;其他的按钮改变5盏灯的状态。 在上图中,左边矩阵中用X标记的按钮表示被按下,右边的矩阵表示灯状态的改变...

Bearing in mind forever! 1222

熄灯问题 - 详解

说明:算法并非原创,来源于网上大神,本文只是对算法进行详细的解释。题目来源 - [NOI OpenJudge]题目描述 有一个由按钮组成的矩阵,其中每行有6个按钮,共5行。每个按钮的位置上有一盏灯。当按下一个按钮后,该按钮以及周围位置(上边、下边、左边、右边)的灯都会改变一次。即,如果灯原来是点亮的,就会被熄灭;如果灯原来是熄灭的,则会被点亮。在矩阵角上的按钮改变3盏灯的状态;在矩阵边上的按钮改

qianli_jiang的博客 1万+

OJ习题详解 1222: EXTENDED LIGHTS OUT,2811: 熄灯问题 C++算法 枚举

欢迎关注笔者,你的支持是持续更博的最大动力 目录问题描述思路枚举改进:枚举局部代码相关内容其他 问题描述 1222: EXTENDED LIGHTS OUT(点击可看详细描述) 中文版2811: 熄灯问题(点击可看中文描述) 简单来说,就是有一组5行6列的灯,每个灯有一个按钮,求一种按按钮方案,可使得所有灯都熄灭。 上图用矩阵表示如下: 要求输出结果:可以熄灭所有灯的按钮的方案。 思路 枚举 这道题可以用枚举的方法解题。刚看到这道题可能有点懵,所以先梳理一下: 最容易想到的应该是,把亮着的灯一.

橘子冰的博客 1900

[C++][枚举]熄灯问题

1.题目 2811:熄灯问题 查看 提交 统计 提示 提问 总时间限制: 1000ms 内存限制: 65536kB 描述 有一个由按钮组成的矩阵,其中每行有6个按钮,共5行。每个按钮的位置上有一盏灯。当按下一个按钮后,该按钮以及周围位置(上边、下边、左边、右边)的灯都会改变一次。即,如果灯原来是点亮的,就会被熄灭;如果灯原来是熄灭的,则会被点亮。在矩阵角上的按钮改变3盏灯的状态;在矩阵边上的按...

BRAVE_NO1的专栏 1756

poj 1222 EXTENDED LIGHTS OUT - 熄灯问题-详解

一个由按钮组成的矩阵,其中每行有6个按钮,共5行。每个按钮的位置上有一盏灯。当按下一个按钮后,该按钮以及周围位置(上边、下边、左边、右边)的灯都会改变一次。即,如果灯原来是点亮的,就会被熄灭;如果灯原来是熄灭的,则会被点亮。在矩阵角上的按钮改变3盏灯的状态;在矩阵边上的按钮改变4盏灯的状态;其他的按钮改变5盏灯的状态。   所以在5x6的矩阵中,左边矩阵中用X标记的按钮表示被按下,右边的矩阵表示...

Patrick的博客 809

OpenJudge百炼-2811-熄灯问题-C语言-枚举

描述: 有一个由按钮组成的矩阵,其中每行有6个按钮,共5行。每个按钮的位置上有一盏灯。当按下一个按钮后,该按钮以及周围位置(上边、下边、左边、右边)的灯都会改变一次。即,如果灯原来是点亮的,就会被熄灭;如果灯原来是熄灭的,则会被点亮。在矩阵角上的按钮改变3盏灯的状态;在矩阵边上的按钮改变4盏灯的状态;其他的按钮改变5盏灯的状态。 在上图中,左边矩阵中用X标记的按钮表示被按下,右边的矩阵

OrdinaryCrazy的博客 2697

熄灯问题 BailianPOJ 2811 或者 BailianPOJ 1222

熄灯问题 BailianPOJ 2811 或者 BailianPOJ 1222 标签(空格分隔): 算法 算法竞赛 题目有些长,就不写了,在北大百炼平台上有,1222是英文版题,2811是中文版。这道题我听的郭炜老师的课,做的真心巧妙,用的也是出乎意料。具体解题思路在下面的代码里,是老师的源程序,我手动敲的。其中有很多个地方不好懂,统一分析在代码最后...

weixin_30481087的博客 190

枚举 熄灯问题

在上图中,左边矩阵中用X标记的按钮表示被按下,右边的矩阵表示灯状态的改变。在下图中,第2行第3、5列的按钮都被按下,因此第2行、第4列的灯的状态就不改变。根据上面的规则,我们知道1)第2次按下同一个按钮时,将抵消第1次按下时所产生的结果。对第1行中每盏点亮的灯,按下第2行对应的按钮,就可以熄灭第1行的全部灯。其中的1表示需要把对应的按钮按下,0则表示不需要按对应的按钮。0表示灯的初始状态是熄灭的,1表示灯的初始状态是点亮的。同样,按下第1、2、3、4、5列的按钮,可以熄灭前5列的灯。

soilovedogs的博客 1152

unity小游戏——熄灯

    在学习数据结构和算法时发现了一道挺有意思的题目:熄灯问题。网上的描述大致是这样:     有一个由按钮组成的矩阵,其中每行有6个按钮,共5行。每个按钮的位置上有一盏灯。当按下一个按钮后,该按钮以及周围位置(上边、下边、左边、右边)的灯都会改变一次。即,如果灯原来是点亮的,就会被熄灭;如果灯原来是熄灭的,则会被点亮。在矩阵角上的按钮改变3盏灯的状态;在矩阵边上的按钮改变4盏灯的状态;其他的...

准程序猿的博客 2821

【PKU算法课0x00】枚举

枚举 何谓枚举? 所谓枚举,就是逐个尝试答案的求解策略。听上去傻傻的,就是把所有的可能都试一遍而已,实则不然。 为什么要枚举? 现实中有很多问题是可以直接用公式求解的。比如已知华氏温度求摄氏温度等,这类问题的时间复杂度是O(1)的,因为这样直接套用公式就能解决,这也是程序设计的最高境界。 然而有很多问题是没有一个确定的数学公式可以解出来的,那我们就只能采用某些策略一个一个的试,这就叫枚举。 当然我...

weixin_41687289的博客 546

遥感图像处理实战:DOTA数据集旋转框转YOLO格式全流程解析(附代码)

本文详细解析了将DOTA遥感数据集的旋转框标注转换为YOLO格式的全流程。针对遥感图像中物体朝向任意性的特点,文章重点阐述了将旋转框转换为外接水平框的数学原理与代码实现,并提供了批量转换脚本和可视化验证方法,帮助开发者高效处理数据,为基于YOLO的遥感目标检测项目奠定基础。

weixin_29082143的博客 398

阔别的很久的博客——熄灯问题

描述 有一个由按钮组成的矩阵,其中每行有6个按钮,共5行。每个按钮的位置上有一盏灯。当按下一个按钮后,该按钮以及周围位置(上边、下边、左边、右边)的灯都会改变一次。即,如果灯原来是点亮的,就会被熄灭;如果灯原来是熄灭的,则会被点亮。在矩阵角上的按钮改变3盏灯的状态;在矩阵边上的按钮改变4盏灯的状态;其他的按钮改变5盏灯的状态。 在上图中,左边矩阵中用X标记的按钮表示被按下,右边的矩阵表示灯状

玄不救非氪不改命 689

李宏毅机器学习笔记第17周_概述领域自适应(Domain Adaptation)

Domain Adaptation

peaunt1的博客 1104

手把手教你复现IEEE 2025高光谱图像盲超分算法DBSR(附开源代码与避坑指南)

本文详细介绍了如何从零复现IEEE 2025高光谱图像盲超分算法DBSR,包括环境配置、数据预处理、核心模块解析、训练策略及常见问题解决方案。特别针对开源代码中的关键步骤和潜在问题提供了实用指南,帮助研究者和开发者高效实现Deep blind super-resolution技术,适用于遥感、医疗等领域的图像增强应用。

weixin_42524708的博客 413

枚举算法——熄灯问题

枚举法练习: 题目: 有 一个由按钮组成的矩阵,其中每行有6个按钮,共5行。每个按钮的位置上有一盏灯。当按下一个按钮后,该按钮以及周围位置(上边、下边、左边、右边)的灯都 会改变一次。即,如果灯原来是点亮的,就会被熄灭;如果灯原来是熄灭的,则会被点亮。在矩阵角上的按钮改变3盏灯的状态;在矩阵边上的按钮改变4盏灯的状 态;其他的按钮改变5盏灯的状态。 在 上图中,左边矩...

dongjiu8975的博客 172

Spring Boot与Apache Ignite集成:构建高性能分布式缓存和计算平台

Apache Ignite是一个高性能的分布式内存计算平台,支持内存缓存、分布式计算、流处理和机器学习等功能。它提供了低延迟的数据访问和强大的计算能力,适用于需要高性能和可扩展性的应用。将Apache Ignite集成到Spring Boot应用中,可以显著提高应用的性能和可扩展性。Spring Boot的简单配置和Ignite的强大功能相结合,使得开发和部署更加高效。首先,创建一个新的Spring Boot项目。可以通过Spring Initializr(https://start.spring.io/)

九天的专栏 2142

熄灯问题

问题描述 熄灯问题 有一个由按钮组成的矩阵,其中每行有6个按钮,共5行。每个按钮的位置上有一盏灯。当按下一个按钮后,该按钮以及周围位置(上边、下边、左边、右边)的灯都会改变一次。即,如果灯原来是点亮的,就会被熄灭;如果灯原来是熄灭的,则会被点亮。在矩阵角上的按钮改变3盏灯的状态;在矩阵边上的按钮改变4盏灯的状态;其他的按钮改变5盏灯的状态。 在上图中,左边矩阵中用X标记的按钮表示被...

serena_0916的博客 2793

搞懂 SAPUI5 Fiori 应用的 OData 授权维护:从 IWSG、IWSV 到 S_SERVICE 的完整实践

本文探讨了SAP Fiori项目中常见的授权问题及其解决方案。文章指出,开发人员常误将OData服务访问问题归咎于前端代码或配置,而实际上多因授权默认值未正确带入角色所致。详细分析了IWSG(前端服务组元数据)和IWSV(后端业务服务)两个关键对象的作用机制,强调应通过PFCG角色的Authorization Default入口维护服务对象,而非直接修改S_SERVICE授权对象。文章还提供了前后端授权配置的具体操作步骤,并特别提醒需同时配置前端和后端授权,才能确保应用完整可用性。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 206

手把手教你玩转服务器芯片架构​专栏--​​3.5 实战案例:用SystemC搭建一个多核服务器芯片的NoC模型(含流量分配与延迟仿真)​

通过SystemC搭建多核NoC模型,可深入验证流量分配策略与延迟特性。实际工程中需结合FPGA原型验证(如Xilinx Alveo)进行时序收敛分析,并通过参数化设计适配不同服务器芯片需求。

MHD0815的博客 3043

python熄灯问题

@python 熄灯问题python def inputaRow() : #本函数用于输入一行灯的状态,返回一个01构成的字符串,一共6个字符,然后将这一个10组成的6个字符的字符串转换成列表结构 #然后在每个列表前后各增加一个0元素,都成一个8个元素的元组,以便于后期扩充成7行8列的方阵 dengrow=input(‘请输入一行6个灯的状态,0表示关灯状态,1表示开灯状态’) while not...

u010768563的博客 1691

NXP(恩智浦)—TJA1043TK CAN收发器芯片详解

本文章主要讲解NXP(恩智浦)—TJA1043TK CAN收发器的相关知识。

零零刷的博客 2201

OPenjudge .熄灯问题

【代码】OPenjudge .熄灯问题。

A18194905282的博客 894

YOLOv11改进 | Neck篇 | 双向特征金字塔网络BiFPN助力YOLOv11有效涨点

本文给大家带来的改进机制是BiFPN双向特征金字塔网络,其是一种特征融合层的结构,也就是我们本文改进YOLOv11模型中的Neck部分,它的主要思想是通过多层级的特征金字塔和双向信息传递来提高精度。本文给大家带来的结构可以让大家自行调节网络结构大小,同时能够达到一定的轻量化效果,为什么发BiFPN呢因为它算是YOLO系列改进中的常青树了,大家可以借鉴它的双向特征思想来创新自己的Neck结构本文的BiFPN通过yaml文件配置可以让大家自行调配其结构。

Snu77的博客 9099

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

上一篇: 变量的定义(JAVA)
下一篇: 用Visual Studio 2022实现五子棋项目【非人机】【保姆级详解】【EasyX库】【供新手教学】【C++】
N-PlusPlus
博客等级 码龄5年 85粉丝 18原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值