凑硬币

来源:互联网 发布:淘宝上怎么找餐饮发票 编辑:程序博客网 时间:2024/04/27 18:03

问题

现有面额为1元,3元,5元的硬币若干枚,如何用最少的硬币凑够11元?


拓展

保证各种面额的硬币数足够多,如何用最少的硬币凑够n元?


Java Code

//版本一:递归求解动态规划问题public int minCoins(int n) {    switch(n) {        case 0: return 0;        case 1: return 1;//面额依次为:1        case 2: return 2;//面额依次为:1,1        case 3: return 1;//面额依次为:3,        case 4: return 2;//面额依次为:1,3        case 5: return 1;//面额依次为:5    }    return Math.min(Math.min(minCoins(n-1), minCoins(n-3)), minCoins(n-5)) + 1;     }//版本二:递推求解动态规划问题public int minCoins2(int n) {    //数组minTable保存每一种总面额下需要的最少硬币数量    int[] minTable = new int[n+1];    minTable[0] = 0;    minTable[1] = 1;    minTable[2] = 2;    minTable[3] = 1;    minTable[4] = 2;    minTable[5] = 1;    for(int i=6; i < minTable.length; ++i)        minTable[i] = Math.min(Math.min(minTable[i-1], minTable[i-3]), minTable[i-5]) + 1;    return minTable[n]; }

说明

  • 解决动态规划问题的一般思路是通过分析寻找原问题的子问题,将原问题的求解转化为子问题的求解,原问题的子问题一般需要分情况讨论。我们可以总结规律得到状态转移方程即递推方程,一般情况下可能还需要总结所有可能的基本情况(比如本题中n=0,1,2,,,5这六种基本情况)。为了简化求解过程,通常需要将已经求解过的子问题结果保存起来(从基本情况开始迭代计算),以便下一次迭代时直接使用,这便是上述代码中的版本二递推解法,如果是从后往前逆推求解,由于当前情况的求解依赖于前一次求解的结果,所以需要用到递归,这便是上述代码中版本一的解法,这种解法的代码通常会显得更加简洁,但是效率不如递推法高。类似问题可以参考Leetcode - Nim Game 。

  • 本题的分析比较简单,n=0,1,2,,,5为基本情况,我们单独分析,从n=6开始,我们使用递推公式来求解最少的硬币数。由于硬币面额只有3种,所以当前总额n的最少硬币数等于n-1、n-3、n-5这三种情况下的最少硬币数的最小值再加1,这个加1就对应于当前次分别用面额等于1、3、5的一枚硬币来凑够n元。

  • 本题不能简单地认为把总额n中的n/5部分金额全部用面额为5的硬币凑,把剩下的的n%5部分金额用面额为1或3的硬币来凑,这种方案不一定就是最优解(本题给的三种面额用此方法正好就是最优解,所以本题可以给出更高效的解法)。举个简单的例子,如果所给的硬币面额为5,4,1三种,当n=8时,如果用本方案则需要的硬币面额分别为5、1、1、1,共需要4枚硬币,而实际上最优解只需要两枚4元硬币即可。

0 0
原创粉丝点击