硬币找零问题描述:现存在一堆面值为 V1、V2、V3 … 个单位的硬币,问最少需要多少个硬币才能找出总值为 T 个单位的零钱?假设这一堆面值分别为 1、2、5、21、25 元,需要找出总值 T 为 63 元的零钱。
很明显,只要拿出 3 个 21 元的硬币就凑够了 63 元了。
基于上述动态规划的思想,我们可以从 T=1 开始计算出最少需要几个硬币,然后再求 T=2 、T=3…每一次求得的结果都保存在一个数组中,以后需要用到时则直接取出即可。
从 T=1 开始依次找零时,可以尝试一下当前要找零的面值 T 是否能够被分解成 另一个已求解的面值的找零需要的硬币个数 再加上 这一堆硬币中的某个面值之和,如果这样分解之后最终的硬币数是最少的,那么问题就得到答案了。
单是上面的文字描述太抽象,先假定以下变量:
values[] : 保存每一种硬币的币值的数组
valueKinds :币值不同的硬币种类数量,即values[]数组的大小
money : 需要找零的面值
dp[] : 保存面值为 i 的纸币找零所需的最小硬币数
算法描述:
当求解总面值为 i 的找零最少硬币数 dp[i] 时,将其分解成求解 dp[i – cents] 和一个面值为 cents 元的硬币,由于 i – cents < i , 其解 dp[ i – cents] 已经在之前的循环中被算出,如果面值为 cents 的硬币满足题意,那么最终解 dp[i] 则等于 dp[i – cents] 再加上 1(