洛谷 P2622 关灯问题II

洛谷P2622

tag:状态压缩

【题目大意】

n个灯,m个按钮,每个按钮都可以控制所有灯,给出每个按钮对每个灯的影响,求从全开到全关的最短步数。

【题目分析】

每盏灯只有两个状态,即开与关,记为0和1,则所有灯的状态总数为2^n(n=3时,有000,001,010,100……)

对每个状态单独分析,可以把每个开关看作一条有向边,这样把不同的状态连起来(也可能出现自环),因此,此题就变成了最短路问题,可以广搜解决。

接下来要考虑的是如何将按钮变成边,即如何确定经过按钮的操作,当前状态将转变成哪个状态。

回想二进制操作(与、或、非、抑或),经过尝试,我们发现“与”操作可以帮助我们解决关灯问题。比如:当原状态为100时(1表示开灯,0关),按钮1可以让1和3号灯关上,我们就可以令按钮1等于010.

100&010=000

“或”操作可以解决开灯问题,如:原状态为110,按钮2可以让1和3打开

110|101=111

当按钮3可以让1和3关上,让2打开时,就可以与010,或010,顺序不会影响结果。

【代码实现】

将二进制直接放到数组里?这是不现实的,所以还是用十进制来实现。

如何提取其中的一位呢?

a & (1<

表示提取a的第j位,若结果是0,说明为0,若结果不为0,说明是1。

标程

#include//2622
using namespace std;
int n , m , state[1200];//n<=10,所以前1023是有用的   表示到达i状态需要走的步数 
int trans[1200][105]; //trans[i][j]表示对状态i按下按钮j的状态 
int q[1200000],now;//q代表即将处理的队列 
int temp,open[110],close[110];
int main()
{
	int l=1,r=1; 
	scanf("%d%d", &n ,&m);
	for( int i = 1 ; i <= m ; i++)  close[i] = (1<

转载于:https://www.cnblogs.com/erutsiom/p/9905157.html

你可能感兴趣的:(洛谷 P2622 关灯问题II)