题目考点判断
这道题其实不是是一个状压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<<j−1次方,即改变第 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<<j−1次方,即改变第 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;
}