美文网首页程序员
动态规划 凑硬币问题

动态规划 凑硬币问题

作者: icecrea | 来源:发表于2017-03-24 15:29 被阅读328次

凑硬币问题

假设有 1 元,3 元,5 元的硬币若干(无限),现在需要凑出 11 元,问如何组合才能使硬币的数量最少?
用数组d来存储当前每个面值可以对应的合成的最小数量
d(i) = d(j) + 1
这里 j < i。通俗地讲,我们需要凑出 i 元,就在凑出 j 的结果上再加上某一个硬币就行了。
那这里加上的哪个硬币呢。把每个硬币试一下就行了:
1.假设最后加上的是 1 元硬币,那 d(i) = d(j) + 1 = d(i - 1) + 1。
2.假设最后加上的是 3 元硬币,那 d(i) = d(j) + 1 = d(i - 3) + 1。
3.假设最后加上的是 5 元硬币,那 d(i) = d(j) + 1 = d(i - 5) + 1。
我们分别计算出 d(i - 1) + 1,d(i - 3) + 1,d(i - 5) + 1 的值,取其中的最小值,即为最优解,也就是 d(i)。
状态转移方程 d(i)=min{d(j)+1},if i>j
d(0)=0;
d(1)=1;
d(2)=d(1)+1=2;
d(3)=min{d(2)+1,d(0)+1}=1;
d(4)=min{d(3)+1,d(1)+1}=2;
d(5)=min{d(4)+1,d(2)+1,d(0)+1}=1;
d(6)=min{d(5)+1,d(3)+1,d(1)+1}=2;

public class test1430 {

        private int[] d; // 储存结果
        private int[] coins = {1,3,5}; // 硬币种类

        private void d_func(int i, int num) {
            if (i == 0) {
                d[i] = 0;
                d_func(i + 1, num);
            }
            else {
                int min = 1000000; // 初始化一个很大的数值。当最后如果得出的结果是这个数时,说明凑不出来。
                for (int coin : coins) {
                    if (i >= coin && d[i - coin] + 1 < min) {//比较得到最小值
                        min = d[i - coin] + 1;
                    }
                }
                d[i] = min;

                if (i < num) {
                    d_func(i + 1, num);
                }
            }
        }


        @Test
        public void test() throws Exception {
            int sum = 11; // 需要凑 11 元
            d = new int[sum + 1]; // 初始化数组

            d_func(0, sum); // 计算需要凑出 0 ~ sum 元需要的硬币数量
            for (int i = 0; i <= sum; i++) {
                System.out.println("凑齐 " + i + " 元需要 " + d[i] + " 个硬币");
            }
        }
}
运行结果

当测试数据换成3、10、12.发现无法合成的数据也可以表示出来。因为其无法参与赋值,所以结果还是设置的Min=1000000


思考:如果要求得需要的最大硬币数 应该如何处理

这里花了我好久的时间 感觉自己真的是蠢 智商不够 想了一种方法 就是用t数组存最大数值,然后每次和max比较,将最大的留下。当然考虑到有的没办法获得,则没办法获得的赋值为0。结合前面的进行更改。写的不好,如果有好一点的方法希望能说一下。

   private static int[] d; // 储存结果
        private static int[] t;
        private static int[] coins = {3,5,6}; // 硬币种类

   private static void d_func_max(int i, int num) {
            if (i == 0) {
                d[i] = 0;
                t[i]=0;
                d_func_max(i + 1, num);
            }
            else {
                int min = 1000000; // 初始化一个很大的数值。当最后如果得出的结果是这个数时,说明凑不出来。
                
                for (int coin : coins) {
                    if (i >= coin && d[i - coin] + 1 < min) {
                        min = d[i - coin] + 1;
                    }
                }
                d[i] = min;
                
                int max=0;
                for (int coin : coins) {
                    if(d[i]==1000000){
                        break;
                    }
                    if (i >= coin && t[i - coin] + 1 > max) {
                        max = t[i - coin] + 1;
                    }
                }
                t[i]=max;
                
                if (i < num) {
                    d_func_max(i + 1, num);
                }
            }
        }
        


        
        public static void main(String[] args){
            int sum = 12; // 需要凑 11 元
            d = new int[sum + 1]; // 初始化数组
            t= new int[sum+1];
            d_func_max(0, sum); // 计算需要凑出 0 ~ sum 元需要的硬币数量
            for (int i = 0; i <= sum; i++) {
                System.out.println("凑齐 " + i + " 元最多需要"+t[i] + " 个硬币");
            }
        }
}

测试数据3、5、6。结果如图


相关文章

  • 动态规划 凑硬币问题

    凑硬币问题 假设有 1 元,3 元,5 元的硬币若干(无限),现在需要凑出 11 元,问如何组合才能使硬币的数量最...

  • 动态规划-凑硬币

    题目描述 给定硬币面额 coins=[c1, c2, c3, ci] 以及金额 N。问最少多少枚硬币可以凑出金额 ...

  • 函数式编程思想

    换硬币问题 问题就是动态规划里面的换硬币问题。所以函数式编程的关键和动态规划问题一样:递归关系式。换硬币问题发现他...

  • 硬币问题-动态规划

    问题描述 假设有 1 元,3 元,5 元的硬币若干(无限),现在需要凑出 11 元,问如何组合才能使硬币的数量最少...

  • 最少硬币问题

    描述:假设你有面值为1块、2块、5块的硬币,用尽可能少的硬币凑n块钱。 贪婪算法和动态规划的问题 此题的贪婪算法很...

  • 07-05:动态规划review2

    动态规划常见问题 零、组合问题 1、硬币问题 n=len(arr) if n<=0 or aim<=0: ...

  • 硬币找零问题——动态规划

    问题阐述 给定一些面值的硬币(数量不限)和需要找零的金额,求一个找零所需硬币数最少的方案。现实生活中因其面值的特殊...

  • 最少硬币动态规划

    有 1,3,5等硬币,给定一个和,计算最少的硬币个数 假设这个和为p(i) i = 0.....n 表示和为i时的...

  • 2018-08-21

    回溯法求子集,有个问题没有解决硬币问题动态规划:趴楼梯的最小代价https://blog.csdn.net/hap...

  • 算法问题——代码实现

    动态规划算法 斐波那契数列的循环实现 最长递增子串 换硬币问题 DTW(Dynamic Time Warping)实现

网友评论

    本文标题:动态规划 凑硬币问题

    本文链接:https://www.haomeiwen.com/subject/snlfottx.html