問題:如果我們有面值爲1元、3元和5元的硬幣若干枚,如何用最少的硬幣湊夠11元?.md

問題

如果我們有面值爲1元、3元和5元的硬幣若干枚,如何用最少的硬幣湊夠11元?

動態規劃的本質是將原問題分解爲同性質的若干相同子結構,在求解最優值的過程中將子結構的最優值記錄到一個表中以避免有時會有大量的重複計算。

例如硬幣組合問題,若求湊夠11元的最少硬幣數,可以先從湊夠0元、1元、2元……的子結構開始分析。

假設d(i)爲湊夠i元所需最少硬幣數,則

d(0) = 0         理所當然

d(1) = 1         要湊夠1元,需要從面值小於等於1元的硬幣中選擇,目前只有面值爲1元的硬幣

            此時d(1) = d(0) + 1

d(2) = d(2 - 1) + 1 = 2, 從面值小於等於2元的硬幣中選擇,符合要求的硬幣面值爲:1元。

            此時d(2) = d(2-1) + 1

d(3) = d(3 - 3) + 1 = 1, 從面值小於等於3元的硬幣中選擇,符合要求的硬幣面值爲:1元,3元。

            此時有有兩種選擇:是否選擇含有面值3元的硬幣

            含有3元硬幣:d(3) = d(3 - 3) + 1 = 1

            不含3元硬幣:d(3) = d(3 - 1) + 1 = d(2) + 1 = 3

            自然是選擇二者中較小值

依次類推…

算法思想

假如要計算11元需要的面值數最小,那麼,11元減去一張1元或者3元或者5元,即10元,8元,6元分別需要的面值數,取出最小,加上1,即可以得到11元最小的。
所以,n元最小問題,是由n-1元,n-3元,n-5元三種狀態裏面取到的最優解。
其中計算的遞歸樹爲:
d(11) = min{d(10),d(8),d(6)} + 1
遞推式
d(i) = min{d(i-v)} + 1,其中v爲面值1,3,5;i爲求值

在這裏插入圖片描述

實現代碼

/**
 * https://www.cnblogs.com/z941030/p/4908115.html
 * https://www.kancloud.cn/qiaodong/datastructure/134483#135_165
 * DP
 * @since 2019-10-25
 */
public class Solution_2019_11_9 {
    // 如果我們有面值爲1元、3元和5元的硬幣若干枚,如何用最少的硬幣湊夠11元
    public int select_coin(int[] coins, int total) {
        // 狀態轉移方程
        int[] minCoins = new int[total + 1];
        minCoins[0] = 0;

        for (int i = 1; i <= total; i++) {
            minCoins[i] = Integer.MAX_VALUE;
            for (int j = 0; j < coins.length; j++) {
                if (coins[j] <= i && minCoins[i - coins[j]] + 1 < minCoins[i]) {
                    minCoins[i] = minCoins[i - coins[j]] + 1;
                }
            }
        }
        System.out.println(Arrays.toString(minCoins));
        return minCoins[total];
    }

    public static void main(String[] args) {
        System.out.println(new Solution_2019_11_9().select_coin(new int[]{1, 3, 5}, 11));
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章