AtCoder Context 128 C Swtich(控制开关)

题目
现有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. 对于电灯泡1,这些开关中,状态是on的开关的个数为偶数的时候会亮:开关1,开关2
  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. 对于电灯泡1,这些开关中,状态是on的开关的个数为偶数的时候会亮:开关1,开关2
  2. 对于电灯泡2,这些开关中,状态是on的开关的个数为偶数的时候会亮:开关1
  3. 对于电灯泡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

这里简单描述为

比特运算.png

代码

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)
阅读 247

推荐阅读