Coins(硬币)题解

1、题目分析

这是蓝书《算法竞赛进阶指南》多重背包的一道例题,硬币为物品,面值为体积,M为背包总容积,我们很容易就分析出这是一个可行性问题而不是一道最优化问题。

这道题我们如果用直接拆分或者二进制拆分的方法做的话都会TLE,但我们如果用单调队列优化是可以AC的,这里给出的是另一种题解。

可行性问题和最优化问题有着本质上的区别,在最优化问题中,我们需要考虑所有的状态有可能这时候不好但转移到下一个阶段就是最优,但可行性问题中只有True和False ,所以我们可以用全局动规,局部贪心的做法让其在阶段 i 时选择尽可能少的 a[i], 这样后面就可以用更多的硬币来拼其他面值,这样一定是最优的,并且让我们省去了一重对 c[i] 的循环,将时间复杂度优化到了O(nm)

这里我们定义一个used数组  used[j] 来记录 f[j]在第 i 阶段为True时,至少需要用多少枚硬币,我们  j 采用完全背包的迭代方式 通过used数组实现多重背包中“物品个数”的限制,代码如下:

代码

import sys

while True:
    n,m = map(int, sys.stdin.readline().split())
    if n == m and n == 0: break
    ls = [0]+list(map(int, sys.stdin.readline().split()))
    used, f = [0]*(m+1), [0]*(m+1)
    f[0] = 1
    for i in range(1, n+1):
        for j in range(1, m+1): used[j] = 0
        for j in range(ls[i], m+1):
            if f[j] == 0 and used[j - ls[i]] < ls[i+n] and f[j-ls[i]]:
                f[j] = 1
                used[j] = used[j - ls[i]] + 1
    ans = 0
    for i in range(1,m+1):
        ans += f[i]
    print(ans)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

farawaytravelerchy

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

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

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

打赏作者

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

抵扣说明:

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

余额充值