Luogu P2622 关灯问题II【状压BFS】

在这里插入图片描述

题目考点判断

这道题其实不是是一个状压DP
而是一道 状 压 B F S 状压BFS BFS 题。
为啥?
它的数据是 n < = 10 n<=10 n<=10,于是我们可以用状态压缩
分析它的题目发现,它的起点一定,终点也一定,求最小步数,~满足边权都为1,很明显是一道状压BFS

思路

将它的状态存到队列里,一开始全部为1,那考虑怎样转移
我们设 a [ i ] [ j ] a[i][j] a[i][j] 表示第 i i i 个开关可以改变第 j j j 个灯
a [ i ] [ j ] = = 1 a[i][j]==1 a[i][j]==1 ,并且当前状态的第 j j j 位为1时,
则当前状态为当前状态 ⊕   1 < < j − 1 \oplus~1<<j-1  1<<j1次方,即改变第 j j j 位上的值为0
a [ i ] [ j ] = = − 1 a[i][j]==-1 a[i][j]==1,并且当前状态的第 j j j 位为0时,
则当前状态为当前状态 ∨   1 < < j − 1 \vee~1<<j-1  1<<j1次方,即改变第 j j j 位上的值为1
(模拟一下即可以推出)

代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;

int f[1<<10][3],a[101][11],v[1<<10];
int n,m;

void bfs()
{
    
    
	int hd=0,tl=1;
	f[1][1]=(1<<n)-1;   //初始化全1
	v[(1<<n)-1]=1;
	while(hd<tl)
	 {
    
    
	 	hd++;
	 	for(int i=1; i<=m; i++)
	 	 {
    
    
	 	 	int s=f[hd][1]; 
	 	 	for(int j=1; j<=n; j++)
	 	 	 {
    
    
	 	 	 	if(a[i][j]==1&&(s&(1<<j-1)))  //情况1
	 	 	 	  s^=(1<<j-1);
	 	 	 	else if(a[i][j]==-1&&!(s&(1<<j-1)))  //情况2
	 	 	 	  s|=(1<<j-1);
	 	 	 }
	 	 	if(!v[s])
	 	 	{
    
    
	 	 	  v[s]=1;     //标记&记录
	 	 	  f[++tl][1]=s;
	 	 	  f[tl][2]=f[hd][2]+1;
	 	 	  if(s==0)
	 	 	   {
    
    
	 	 	   	 printf("%d",f[tl][2]);
	 	 	   	 return;
	 	 	   }
	 	 	}
	 	 }
	 }
	printf("-1");
}
int main()
{
    
    
    cin>>n>>m;
    for(int i=1; i<=m; i++)
     for(int j=1; j<=n; j++)
        scanf("%d",&a[i][j]);
    bfs();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Jackma_mayichao/article/details/108118786
今日推荐