枚举算法(熄灯问题)

上课笔记:图片截图自慕课网的视频

问题描述

有一个由按钮组成的矩阵,其中每行有6个按钮,共5行。每个按钮的位置上有一盏灯。当按下一个按钮后,该按钮以及周围位置(上边、下边、左边、右边)的灯都会改变一次。即,如果灯原来是点亮的,就会被熄灭;如果灯原来是熄灭的,则会被点亮。在矩阵角上的按钮改变3盏灯的状态;在矩阵边上的按钮改变4盏灯的状态;其他的按钮改变5盏灯的状态。
请你写一个程序,确定需要按下哪些按钮,恰好使得所有的灯都熄灭。

在这里插入图片描述
输入输出描述:
在这里插入图片描述

解题思路:

首先分析:根据上述的规则我们可以得出

  • 第2次按下同一个按钮时,将抵消第1次按下时所产生的结果。因此,每个按钮最多只需要按下一次;
  • 各个按钮被按下的顺序对最终的结果没有影响;
  • 对第1行中每盏点亮的灯,按下第2行对应的按钮,就可以熄灭第1行的全部灯。如此重复下去,可以熄灭第1、2、3、4行的全部灯。同样,按下第1、2、3、4、5列的按钮,可以熄灭前5列的灯。

第一想法:枚举所有可能的按钮(开关)状态,对每个状态计算最后灯的情况,看是否都熄灭;但是,一共有30个开关,那么状态数2的30次方,太大,会超时
第二想法:我们可不可以找到某个局部。只要这个局部能够确定下来,整个30个灯的状态就可以确定。我们就可以很明显的发现,第一行就是这样的局部,来简单分析一下:

Created with Raphaël 2.2.0 当第一行确定之后 想要熄灭第一行的灯,唯一的方法就是按下第二行的开关; 同理,想要熄灭第二行的灯,只能按下的三行的灯 所以第一行这个“局部”确定后; 整个30个灯的状态就确定 yes

所以:我们只需枚举第一行的状态,状态数就是2的6次方=64

在用代码实现的时候可以使用的一些方法:
1、首先解决的问题就是把灯以及开关的状态存起来(这里我们可以使用一个char类型的一位数组来存)
2、0代表关,1代表开。可以利用二进制进行枚举由k位的“0”“1”组成的组合,这个组合可以与int类型的(0到2的k次方 -1)2的k次方个数一一对应。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值