"""
题目来源:
https://www.lanqiao.cn/courses/21963/learning/?id=1624416&compatibility=false
"""
n, m, k = map(int, input().split())
# 数组a记录每包糖果的状态, 状态用二进制表示
# 例如二进制数10101表述该包糖果有第1, 3, 5种类的糖果, 没有第2, 4类的糖果
a = [0] * (n + 1)
for i in range(1, n + 1):
# 读入每包糖果
x = [0] + list(map(int, input().split()))
# 遍历每颗糖果
for j in range(1, k + 1):
a[i] |= 1 << (x[j] - 1)
# 比如, 如果该课糖果是第6类糖果就用二进制100000表示, 等同于1 << (x[j] - 1)。
# 如果将该包中所有糖果进行或运算, 得到的二进制数就能表示该包糖果含有糖果种类的状态。
# 比如三颗糖果的种类为6, 5, 6, 将其进行或运算就是100000 | 010000 | 100000 == 110000,
# 结果显示示该包糖果含有第5, 6种类的糖果。
# dp[i]表示想要获得i状态时种类数的糖果, 最小需要购买的糖果包数
# 假如m种糖果都获得了, 状态值就是2 ** m - 1
# 所以dp数组的长度为2 ** m
dp = [float('inf')] * (1 << m)
dp[0] = 0 # 最小访问次数
# 访问每包糖果
for i in range(1, n + 1):
# 对于每包糖果, 枚举每种状态, 不断对状态需要的糖果包数进行更新
for j in range(1 << m):
# 将原来得到糖果所需的次数与当前次数+1(要这袋糖果)比较并赋值
dp[j | a[i]] = min(dp[j | a[i]], dp[j] + 1)
# (1 << m) - 1 == 2 ** m - 1, 表示都买到的状态。
if dp[(1 << m) - 1] > n:
print(-1)
else:
print(dp[(1 << m) - 1])
蓝桥杯--糖果
于 2024-03-14 17:49:07 首次发布
![](https://img-home.csdnimg.cn/images/20240711042549.png)