蓝桥杯--糖果

本文介绍了一种通过二进制表示糖果种类的策略,利用动态规划求解在给定条件下,获取特定糖果状态所需的最小糖果包数问题。如果无法达到所有糖果种类,输出-1;否则,给出所需的最小包数。
摘要由CSDN通过智能技术生成
"""
题目来源: 
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])

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

好无聊啊,烦死

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值