题目
现有N个开关,它们有on和off两种状态,还有M个电灯泡。开关编号从1到N,电灯泡编号从1到M。电灯泡i和Ki个的开关连接在一起。这些开关的编号从Si1,Si2,Si3,Si4,....Siki.电灯泡i的ki个开关中,状态为on的开关的个数如果和pi的值相等的时候,电灯泡ki将会亮起。
能够让所有的灯泡亮起的的开关组合有多少种?
条件
- 1<=N,M<=10
- 1<=Ki<=N
- 1<=Sij<=N
- Sia != Sib (a != b)
- Pi为0或者1
- 所有的输入都为整数
输入
要求以下面的方式输入
N M
k1 s11 s12 ...... s1k1
.
.
km sm1 sm2 ...... smkm
p1 p2 ...... pm
输出
能够让所有灯泡都亮的开关的组合数
例1
输入
2 2
2 1 2
1 2
0 1
输出
1
解释
- 对于电灯泡1,这些开关中,状态是on的开关的个数为偶数的时候会亮:开关1,开关2
- 对于电灯泡2,这些开关中,状态时on的开关的个数为奇数的时候会亮:开关2
对于开关1和开关2来说,所有的情况是以下
(on,on),(on,off),(off,on),(off,off)
能够满足以上条件的只有(on,on),暨开关1开,开关2开。
最后输出1
例2
输入
2 3
2 1 2
1 1
1 2
0 0 1
输出
0
解释
- 对于电灯泡1,这些开关中,状态是on的开关的个数为偶数的时候会亮:开关1,开关2
- 对于电灯泡2,这些开关中,状态是on的开关的个数为偶数的时候会亮:开关1
- 对于电灯泡3,这些开关中,状态是on的开关的个数为奇数的时候会亮:开关2
为了保证电灯泡2开,开关1要off
为了保证电灯泡3开,开关2要on
这种情况下,电灯泡1,不可能亮起
所以,让所有的电灯泡都能亮的情况是不存在的,输出为0
例3
输入
5 2
3 1 2 5
2 2 3
1 0
输出
8
解题思路
读懂题目
遍历所有的开关关闭情况,看看是不是满足所有的电灯泡亮起的条件
N代表开关的数量,N的最大值是10,开关有on,off两种情况,所以一共有2的10次方,1024种情况。一个for循环,时间上老说是足够的
那么问题来了,如何用代码实现这1024种情况呢
答案就在比特运算
打个比方,有3个开关,一共2的3次方种情况,一共8种情况
for i in range(2**3):
print(i)
这样能输出
0
1
2
3
4
5
6
7
但是实际上可以看成
000
001
010
011
100
101
110
111
其中011可以看成
开关3(OFF)
开关2(ON)
开关1(ON)
这里我们当然能够从肉眼中简单判断出以上的情况,那么如何从代码中判断,011的情况中第三个开关是OFF呢
有一个技巧
判断开关3是否为ON
3 >> 2 & 1
这里简单描述为
代码
def calculate(n,m,arr,p):
total = 0
for i in range(2**n):
#某一种情况
check = [False for i in range(m)]
for indexOfBlub in range(len(arr)):
# 第几个灯泡
onNumOfTheBlub = 0
for indexOfSwitch in range(len(arr[indexOfBlub])):
if i >> (arr[indexOfBlub][indexOfSwitch] - 1) & 1:
onNumOfTheBlub += 1
# 该灯泡所有的switch都循环结束以后,统计on的数量是否和给定的一样
if onNumOfTheBlub % 2 == p[indexOfBlub]:
check[indexOfBlub] = True
if all(check):
total += 1
return total
S = input()
S = S.split(" ")
n = int(S[0])
m = int(S[1])
inputArr = []
for i in range(m):
S = input()
inputArr.append([int(s) for s in S.split(" ")][1:])
S = input()
inputP = [int(s) for s in S.split(" ")]
res = calculate(n,m,inputArr,inputP)
print(res)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。