动态规划算法求解硬币找零问题
动态规划的基本思想是将待求解问题分解成若干个子问题,先求解子问题,并将这些子问题的解保存起来,如果以后在求解较大子问题的时候需要用到这些子问题的解,就可以直接取出这些已经计算过的解而免去重复运算。保存子问题的解可以使用填表方式,例如保存在数组中。
用一个实际例子来体现动态规划的算法思想——硬币找零问题。
硬币找零问题描述:现存在一堆面值为 V1、V2、V3 … 个单位的硬币,问最少需要多少个硬币才能找出总值为 T 个单位的零钱?假设这一堆面值分别为 1、2、5、21、25 元,需要找出总值 T 为 63 元的零钱。
很明显,只要拿出 3 个 21 元的硬币就凑够了 63 元了。
基于上述动态规划的思想,我们可以从 1 元开始计算出最少需要几个硬币,然后再求 2 元、3元…每一次求得的结果都保存在一个数组中,以后需要用到时则直接取出即可。那么我们什么时候需要这些子问题的解呢?如何体现出由子问题的解得到较大问题的解呢?
其实,在我们从 1 元开始依次找零时,可以尝试一下当前要找零的面值(这里指 1 元)是否能够被分解成另一个已求解的面值的找零需要的硬币个数再加上这一堆硬币中的某个面值之和,如果这样分解之后最终的硬币数是最少的,那么问题就得到答案了。
单是上面的文字描述太抽象,先假定以下变量:
values[] : 保存每一种硬币的币值的数组
valueKinds :币值不同的硬币种类数量,即values[]数组的大小
money : 需要找零的面值
coinsUsed[] : 保存面值为 i 的纸币找零所需的最小硬币数
算法描述:
当求解总面值为 i 的找零最少硬币数 coinsUsed[ i ] 时,将其分解成求解 coinsUsed[ i – cents]和一个面值为 cents 元的硬币,由于 i – cents < i , 其解 coinsUsed[ i – cents] 已经存在,如果面值为 cents 的硬币满足题意,那么最终解 coinsUsed[ i ] 则等于 coinsUsed[ i – cents] 再加上 1(即面值为 cents)的这一个硬币。
下面用代码实现并测试一下:
public class CoinsChange { /** * 硬币找零:动态规划算法 * * @param values * :保存每一种硬币的币值的数组 * @param valueKinds * :币值不同的硬币种类数量,即coinValue[]数组的大小 * @param money * :需要找零的面值 * @param coinsUsed * :保存面值为i的纸币找零所需的最小硬币数 */ public static void makeChange(int[] values, int valueKinds, int money, int[] coinsUsed) { coinsUsed[0] = 0; // 对每一分钱都找零,即保存子问题的解以备用,即填表 for (int cents = 1; cents <= money; cents++) { // 当用最小币值的硬币找零时,所需硬币数量最多 int minCoins = cents; // 遍历每一种面值的硬币,看是否可作为找零的其中之一 for (int kind = 0; kind < valueKinds; kind++) { // 若当前面值的硬币小于当前的cents则分解问题并查表 if (values[kind] <= cents) { int temp = coinsUsed[cents - values[kind]] + 1; if (temp < minCoins) { minCoins = temp; } } } // 保存最小硬币数 coinsUsed[cents] = minCoins; System.out.println("面值为 " + (cents) + " 的最小硬币数 : " + coinsUsed[cents]); } } public static void main(String[] args) { // 硬币面值预先已经按降序排列 int[] coinValue = new int[] { 25, 21, 10, 5, 1 }; // 需要找零的面值 int money = 63; // 保存每一个面值找零所需的最小硬币数,0号单元舍弃不用,所以要多加1 int[] coinsUsed = new int[money + 1]; makeChange(coinValue, coinValue.length, money, coinsUsed); } }
面值为 1 的最小硬币数 : 1
面值为 2 的最小硬币数 : 2
面值为 3 的最小硬币数 : 3
面值为 4 的最小硬币数 : 4
面值为 5 的最小硬币数 : 1
面值为 6 的最小硬币数 : 2
...
...
面值为 60 的最小硬币数 : 3
面值为 61 的最小硬币数 : 4
面值为 62 的最小硬币数 : 4
面值为 63 的最小硬币数 : 3
上面的代码并没有给出具体应该是哪几个面值的硬币,这个可以再使用一些数组保存而打印出来。
分享到:
相关推荐
在这个“算法设计与分析之动态规划求解硬币问题”的案例中,我们将探讨如何使用动态规划方法来解决一个经典的组合优化问题:硬币找零问题。 硬币找零问题的基本设定是这样的:你有一组不同面值的硬币,目标是找出...
本算法通过动态规划的方式解决最少硬币找零问题,不仅确保了算法的时间效率,还提供了最优解。 #### 问题描述 假设我们有 _n_ 种不同面值的硬币,每种硬币的面值分别存储在数组 _T_[1:_n_] 中。现在我们需要使用...
动态规划算法的核心思想在于将复杂问题分解为多个子问题,并通过解决这些子问题来获得原问题的解决方案。这种方法特别适用于那些子问题相互关联且存在重叠的情况。动态规划算法通常包括以下几个步骤: 1. **最优子...
6. **边界条件**:设计动态规划算法时,要先确定基础情况,即最小规模的子问题,它们可以直接求解,然后逐步扩展到更大规模的问题。 7. **动态规划的分类**:动态规划可以分为自底向上和自顶向下两种方法。自底向上...
动态规划算法设计的关键在于识别问题的最优子结构和状态转移方程,然后通过构造合适的数据结构(如数组或矩阵)存储子问题的解,并按照一定顺序(通常是自底向上或自顶向下)计算整个问题的解。理解这些概念并能够...
"找零动态规划算法"是这种思想的一个实际应用,它涉及到如何有效地计算出给予一定金额时,最少数量的硬币组合。在这里,我们将深入探讨这种算法以及如何使用C++和C语言实现。 动态规划的核心在于构建一个最优解的...
Java动态规划之硬币找零问题实现代码可以通过动态规划的思想来解决硬币找零问题,通过将问题分解成多个子问题,从而避免重复运算,提高算法的效率。 希望这篇文章能够对大家有所帮助。如果您有任何问题或建议,请...
动态规划(Dynamic Programming,简称DP)是一种用于解决最优化问题的算法思想,它通过将大问题分解为相互重叠的子问题,并存储子问题的解,以避免重复计算,从而达到高效求解的目的。DP的核心在于它能够识别并利用...
- 根据读取的数据初始化 `T` 和 `Coins` 数组,然后执行上述动态规划算法。 - 结果输出到 `output.txt`,包含计算出的最少硬币数,或在无解时输出 `-1`。 在给定的输入文件 `input.txt` 示例中,有 3 种面值的硬币...
通过上述动态规划算法,我们可以有效地解决找最轻硬币的问题,而不需要尝试所有可能的硬币组合。这种方法不仅适用于找零问题,还可以扩展到其他需要最小化成本或寻找最优解的场景,比如旅行商问题、最长公共子序列等...
例如,当我们需要找寻最小硬币找零问题时,贪婪算法会选择每次找最大的硬币,直到找零金额满足。然而,贪婪算法并不总是能得到全局最优解,因为它可能过于乐观地假设局部最优即为全局最优,忽略了长远的影响。 接...
初始状态d[0]为0,因为不需要任何硬币找零0元。 接下来,我们可以使用动态规划的思想来构建解决方案。动态规划的核心是将大问题分解为小问题,然后逐个解决。对于最少硬币问题,我们可以通过以下递推公式来求解: ...
在硬币找零问题中,我们可以使用动态规划来构建一个解决方案。 首先,我们需要理解动态规划的基本思想。动态规划通过将大问题分解为小问题,然后逐步解决这些小问题,最终得到大问题的解。在硬币找零问题中,我们...
贪婪算法是一种在每一步选择中都采取在当前状态下最好或最优(即最有利)的选择,从而希望导致结果是...因此,在设计算法时,需要根据问题特性谨慎选择是否采用贪婪策略,并结合其他算法,如动态规划,以提高解的质量。
10. **硬币找零问题**:给定不同面额的硬币,求解找零的最少硬币数,dp[i]表示找零i元所需的最少硬币数。 11. **约瑟夫环**:动态规划可以解决约瑟夫环问题,即每隔一定数目的人报数,报到的人出局,最后剩下的人是...
这个问题可以用动态规划解决,创建一个状态转移方程来表示用不同面值硬币找零的过程。 总的来说,这个压缩包包含的内容涵盖了算法设计和分析的重要方面,从基本的排序和搜索到更高级的问题解决策略,如动态规划和最...
这类问题通常可以通过动态规划算法进行高效求解。本篇文章将详细探讨一种特定的找零问题——最少硬币问题,并给出其算法实现。 #### 问题定义 设有 \( n \) 种不同面值的硬币,各硬币的面值存于数组 \( T[1:n] \) ...
动态规划是一种强大的算法思想,广泛应用于计算机科学,特别是在优化问题和计算问题中。在这个主题“动态规划经典应用”中,我们将深入探讨三个具体的问题:找零钱问题、最长公共字符串问题(LCS)以及背包问题,并...
【标签】"代码"表明这是一个关于编程实践的问题,重点在于理解和实现动态规划算法。 【压缩包子文件的文件名称列表】中的`main.js`是包含上述JS代码的主文件,通常在Node.js环境中执行。`README.txt`可能是对项目或...
在动态规划中,我们不是通过递归的方式反复求解相同的子问题,而是将子问题的解存储起来,避免了重复计算,从而提高了算法的效率。 1. **动态规划概述** 动态规划的核心思想是将复杂的问题分解成一系列较小的子...