洛谷 P2622 关灯问题II (状态压缩动态规划)

该博客讨论了洛谷P2622题目,即如何通过控制m个按钮来关闭n盏灯的最少操作次数。作者提出了用状态压缩动态规划的方法,初始状态为全开,通过位运算或bitset操作更新灯的状态,并利用BFS找到到达所有状态的最短路径。文章包含问题描述、解题思路及C++代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

P2622 关灯问题II

题意

给定n盏灯,以及m个按钮。每个按钮可以同时控制这n盏灯,按下了第i个按钮,对于所有的灯都会有一个效果。按下i按钮对于第j盏灯,是下面3中效果之一:如果a[i][j]为1,那么当这盏灯开了的时候,把它关上,否则不管;如果为-1的话,当这盏灯是关的,把它打开,否则也不管;如果是0,无论这灯是否开,都不管。

现在这些灯都是开的,给出所有开关对所有灯的控制效果,求问最少要按几下按钮才能全部关掉。

n < = 10 , m < = 100 n<=10,m<=100 n<=10,m<=100

思路

用n位二进制数表示这n盏灯的状态,0为关,1为开。
则初始状态为 000000…000。
d p [ x ] dp[x] dp[x]表示得到 x x x这个状态需要按下按钮的最小次数,即有 d p [ 0 ] = 0 dp[0] = 0 dp[0]=0

然后我们从状态0开始,依次按下每个按钮,得到其他状态y,当y状态第一次出现时,就得到了状态y的最小次数,即 d p [ y ] = d p [ x ] + 1 dp[y] = dp[x]+1 dp[y]=dp[x]+1
当然,如果得不到这个状态,就输出-1。

也可以这么理解,我们把所有的状态看作点,状态之间的转移看作边,则最开始我们有一个状态为0初始点,通过按按钮,我们可以通过该点得到其他点,则在这两点之间连一条边权为1的边,最终,从起点出发,到每个点的最短路就是要获得每个状态的最少次数。但我们没有必要去跑一便最短路,每个点第一个被连接到时所消耗的次数,就是它的最短路。(说白了就是在BFS)

代码

附上两份代码,思路一致,具体实现略有不同。
另外,如果不想自己用位运算提取状态的话,也可以用C++STL的bitset实现。

#include<bits/stdc++.h>

using namespace std
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值