Diaries Algorithm-零錢兌換

1 換硬幣問題
在這裏插入圖片描述
給定任意問題,我們總能找到該問題最簡單的案例,針對簡單的例子,我們往往能很快得到答案。再考慮難一些的例子,即更常規的例子,我們如何解決呢?顯然,我們希望大事化小,小化了,因此,我們首先考慮原問題是否可分爲子問題?顯然該問題是由子問題amount-1的最優解組成。具備最優子結構性質的問題往往用動態規劃解決。此外,另一個十分重要的問題就是如何確定遞推表達式,也稱爲狀態轉移方程。如何確定狀態轉移方程呢?
(1)確定狀態
該問題中,子問題和原問題的變量是什麼呢?
金額
硬幣面額
硬幣數目:無限多硬幣,不影響
(2)確定狀態轉移函數定義
opt(n)表示湊出金額爲n,所需最少的硬幣數
(3)如何確定最優
從coins中任意選擇一枚硬幣,金額數減少,怎麼選才能使硬幣數目最少?我們將各個選擇下所需硬幣數求出來,最優決策就是能使硬幣數目最少的決策方式。因此我們獲取狀態轉移方程:
在這裏插入圖片描述

// 回溯
int coinChange(vector<int>& coins, int amount){
    if (amount == 0)
    {
        return 0;
    }
    else if (amount < 0)
    {
        return -1;
    }
    else 
    {
        int res = INT16_MAX;
        for (int i = 0;i < coins.size();i++)
        {
            int subp = coinChange(coins,amount - coins[i]);
            if (subp != -1)
            {
                res = min(res,subp +1 );
            }
        }

        if (res == INT16_MAX)
        {
            return -1;
        }else
        {
            return res;
        }
    }
}
//DP 
int coinChange(vector<int> &coins, int amount)
{
    if (amount == 0)
        return 0;
    if (amount < 0)
        return -1;
    vector<int> opt(amount+1, amount+1);
    opt[0] = 0;
    int n = coins.size();
    for (int i = 1; i <= amount; i++)
    {
        for (int j = 0; j < n; j++)
        {
            if ((i - coins[j]) >= 0)
            {
                opt[i] = min(opt[i], opt[i - coins[j]] + 1);  
            }
        }
    }
    if (opt[amount] >= amount + 1)
    {
        return -1;
    }
    return opt[amount];
}

reference:
https://labuladong.gitbook.io/algo/dong-tai-gui-hua-xi-lie/dong-tai-gui-hua-xiang-jie-jin-jie

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章