题目大意:
有一些灯,有些开关可以控制这些灯,给出矩阵表示控制
对于矩阵中的a i j 表示第i个开关控制第j个灯的情况
若元素为1 表示当灯开着的时候,关掉灯
若元素为0 表示无操作
若元素为-1 表示当灯关着的时候,打开灯
思路:
因为灯的数量很小
我们可以将所有灯的状态用二进制来表示
然后我们跑一下所有状态的spfa
位运算记错了毁一生:
| 或 有一个是1就为1
^ 异或 不一样就为1
& 与 两个都是1才为1
~(1<<j) 表示除了第j位全部为1
1 #include<iostream>
2 #include<cstdio>
3 #include<cmath>
4 #include<algorithm>
5 #include<cstring>
6 #include<cstdlib>
7 #include<queue>
8 #include<vector>
9 #include<set>
10 #include<stack>
11 #define inf 2147483647
12 #define ll long long
13 #define MOD 1000000000
14 #define MAXN 22
15 using namespace std;
16 inline int read()
17 {
18 int x=0,f=1;
19 char ch=getchar();
20 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
21 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
22 return x*f;
23 }
24 int n,m,dis[MAXN*100],cnt;
25 bool vis[MAXN*100];
26 short map[MAXN*5][MAXN];
27 int spfa()
28 {
29 queue <int> q;
30 int tmp;
31 q.push(cnt);vis[cnt]=1;
32 dis[cnt]=0;
33 while(!q.empty())
34 {
35 int k=q.front();
36 q.pop();
37 for(int i=1;i<=m;i++)
38 {
39 tmp=k;
40 for(int j=0;j<n;j++)
41 {
42 if(map[i][j]==1) tmp=tmp&(~(1<<j));
43 if(map[i][j]==-1) tmp=tmp|(1<<j);
44 }
45 if(dis[tmp]>dis[k]+1)
46 {
47 dis[tmp]=dis[k]+1;
48 if(!vis[tmp]) {vis[tmp]=1;q.push(tmp);}
49 }
50 }
51 vis[k]=0;
52 }
53 if(dis[0]>=2*MOD) return -1;
54 return dis[0];
55 }
56 int main()
57 {
58 n=read(),m=read();
59 for(int i=1;i<=m;i++)
60 for(int j=0;j<n;j++) map[i][j]=read();
61 memset(dis,127,sizeof(dis));
62 cnt=(1<<n)-1;
63 printf("%d",spfa());
64 }