我的第二篇题解hhh
虽然网上可以搜到的该题的题解并不少,而且都能确定出是“多重背包”的解法。但是对于“背包”和“物品”的描述,我感觉交待的并不是很清楚,至少对于像我这样的初学者来说,是不容易理解的。
这篇博客可以帮助你更好的理解这个题目,但是你必须有多重背包的基础。
————————————————————————————————————
原题
题意
有各种不同面额的货币,每种面额的货币有不同的数量。
请找出利用这些货币可以凑成的最接近且小于等于给定的数字cash的金额。
思路
很显然的多重背包。
但是如何去理解这道题目中的背包和物品的划分呢?
背包的容量:cash
。
背包最终可获得的最大价值:实际得到的钱的价值,即答案
。
物品的种类:面额种类数
。
每种物品的数量:钱的张数
。
每种物品的价值和重量:面额
。
为什么物品的价值和重量都是这种金钱的面额呢?
当你取一张面额为100的钞票时,你就得到了100元,即价值为100。
同时,你还可以取cash - 100,即重量为100。
背包的容量为cash代表最多可以取cash元钱,而实际上取到了多少钱则需要看它最终的价值。
优化
直接将n[i]个面额相同的钞票(一种物品)理解为n种不同的物品,然后套用01背包,复杂度为O(V*Σn[i])
,肯定是会超时的。
因此我们可以通过二进制优化的方法将复杂度优化到O(V*Σlogn[i])
,至于如何实现,你可以参照其他的博客或者《背包九讲》,在此就不赘述了(其实是我讲得很烂
除此之外,你还可以参照《背包九讲》,利用单调队列的方法,将时间复杂度优化到O(V*N)
,但是我也不太懂,所以这里也不再提了…
代码
#include <iostream>
#