• 硬币兑换问题


    描述:给定总金额为A 的一张纸币,现要兑换成面额分别为a1, a2,…, an 的硬币。硬币兑换问题是用最少枚数的硬币来兑换总金额为A 的纸币。

    如 a = {1, 2, 5},兑换6元则要2枚硬币(1和5)。根据特定的a,有可能可以直接用贪心算法每次都选取可用的最大硬币值。但对于一些例子,会出现错误情况。

    如 a = {1, 4, 5},兑换8元。若直接选取最大值,则需要4枚(1个5和3个1),但显然最优值应为2枚(2个4)。

    对于兑换n元的硬币的最优情况,可以遍历列表 a ,分别选取1个其面值的硬币,再从中挑出最优结果,此时 f(n) = min{f(n-ai)+1}。而每个之前算法的结果都可能被后面的结果重复使用。满足动态规划中的最优子结构和重叠子问题。

    算法基本思路:

    1.计算最小枚数;

    如前所述,设 f[i] 表示兑换 i 元所需要的最小枚数硬币,初始化 f[0] = 0.

    f[i] = min{f[i-a[j]] + 1}, 其中 i >= a[j], 0 <= j < a.length

    2.构造最小枚数所需的各个硬币。

    在上面的基础上,设 rest[i] 表示经过本次兑换后所剩下的面值,即 i - rest[i] 可得到本次兑换的硬币值。

    从 k = n 开始,逆推可构建整个路线(k = rest[k])。

    public class ChangeCoins{
    
        public static int getChanges(int[] a, int n){
            /*
            a: all kinds of coins
            minNum: the min number of coins
            rest: the rest money after using this coin
            */
            if(n < 0)
                return -1;
            //init
            int[] minNum = new int[n+1];
            int[] rest = new int[n+1];
            minNum[0] = 0;
            //dynamic programming
            for(int i = 1; i <= n; i ++){
                int min = i;
                for(int j = a.length-1; j >= 0; j --){
                    if(i >= a[j] && min > 1 + minNum[i-a[j]]){
                        min = 1 + minNum[i-a[j]];
                        rest[i] = i-a[j];
                    }
                }
                minNum[i] = min;
            }
            //build the path
            int k = n;
            while(rest[k] != 0){
                System.out.print((k-rest[k]) + " ");
                k = rest[k];
            }
            System.out.println(k);
            return minNum[n];
        }
    
        public static void main(String[] args) {
            int[] a = {1, 4, 5};
            int n = 8;
            System.out.println(n + ": ");
            System.out.println(getChanges(a, n));
        }
        
    }
    Java
  • 相关阅读:
    Topcoder SRM656div1 250 ( 期望DP )
    SCAU 2015 GDCPC team_training1
    第五次群赛暨清明节专场
    HDU 2783 You’ll be Working on the Railroad(最短路)
    HDU 4013 Distinct Subtrees(树的最小表示)
    HDU 4014 Jimmy’s travel plan(图计数)
    SCAU 2015 GDCPC team_training0
    HDU 1024 Max Sum Plus Plus (递推)
    UVA 12849 Mother’s Jam Puzzle( 高斯消元 )
    HDU 4285 circuits( 插头dp , k回路 )
  • 原文地址:https://www.cnblogs.com/7hat/p/3462951.html
Copyright © 2020-2023  润新知