基本动态规划之硬币问题

硬币问题

问题描述

假设有 1 元,3 元,5 元的硬币若干(无限),如今须要凑出 11 元,问如何组合才能使硬币的数量最少?java

问题分析

乍看之下,咱们简单的运用一下心算就能解出须要 2 个 5 元和 1 个 1 元的解。固然这里只是列出了这个问题比较简单的状况。当硬币的币制或者种类变化,而且须要凑出的总价值变大时,就很难靠简单的计算得出结论了。贪心算法能够在必定的程度上得出较优解,但不是每次都能得出最优解。算法

这里运用动态规划的思路解决该问题。按照通常思路,咱们先从最基本的状况来一步一步地推导。数组

咱们先假设一个函数 d(i) 来表示须要凑出 i 的总价值须要的最少硬币数量。函数

  1. i = 0 时,很显然咱们能够知道 d(0) = 0。由于不要凑钱了嘛,固然也不须要任何硬币了。注意这是很重要的一步,其后全部的结果都从这一步延伸开来
  2. i = 1 时,由于咱们有 1 元的硬币,因此直接在第 1 步的基础上,加上 1 个 1 元硬币,得出 d(1) = 1
  3. i = 2 时,由于咱们并无 2 元的硬币,因此只能拿 1 元的硬币来凑。在第 2 步的基础上,加上 1 个 1 元硬币,得出 d(2) = 2
  4. i = 3 时,咱们能够在第 3 步的基础上加上 1 个 1 元硬币,获得 3 这个结果。但其实咱们有 3 元硬币,因此这一步的最优结果不是创建在第 3 步的结果上得来的,而是应该创建在第 1 步上,加上 1 个 3 元硬币,获得 d(3) = 1
  5. ...

接着就再也不举例了,咱们来分析一下。能够看出,除了第 1 步这个看似基本的公理外,其余日后的结果都是创建在它以前获得的某一步的最优解上,加上 1 个硬币获得。得出:code

d(i) = d(j) + 1blog

这里 j < i。通俗地讲,咱们须要凑出 i 元,就在凑出 j 的结果上再加上某一个硬币就好了。io

那这里咱们加上的是哪一个硬币呢。嗯,其实很简单,把每一个硬币试一下就好了:class

  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) + 1d(i - 3) + 1d(i - 5) + 1 的值,取其中的最小值,即为最优解,也就是 d(i)test

最后公式:基础

代码示例

这里用 Java 实现了基本的代码:

public class CoinProblemBasicTest {

    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 = 9999999; // 初始化一个很大的数值。当最后若是得出的结果是这个数时,说明凑不出来。
            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] + " 个硬币");
        }
    }
}

结果以下:

凑齐 0 元须要 0 个硬币
凑齐 1 元须要 1 个硬币
凑齐 2 元须要 2 个硬币
凑齐 3 元须要 1 个硬币
凑齐 4 元须要 2 个硬币
凑齐 5 元须要 1 个硬币
凑齐 6 元须要 2 个硬币
凑齐 7 元须要 3 个硬币
凑齐 8 元须要 2 个硬币
凑齐 9 元须要 3 个硬币
凑齐 10 元须要 2 个硬币
凑齐 11 元须要 3 个硬币
相关文章
相关标签/搜索