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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值