动态规划,零钱兑换问题

动态规划也可以用来解决零钱兑换问题。这个问题是给定不同面额的硬币和一个总金额,计算出组成该总金额所需的最少硬币数。如果不能凑出总金额,则返回 -1。

好的,让我们通过一个具体的例子来说明动态规划零钱兑换的过程。

假设有以下情况:

 

1.给定面额为 [1, 2, 5] 的硬币。

2.目标总金额为 11。

 

我们的目标是计算出组成总金额 11 所需的最少硬币数。

 

3.初始化:

我们首先初始化一个长度为 12 的数组 dp,其中 dp[i] 表示组成金额 i 所需的最少硬币数。由于金额从 0 到 11,所以数组长度为 12。

 

   dp = [0, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF, INF]

 

这里用 INF 表示正无穷,表示当前状态下还不能组成对应的金额。

 

4.状态转移:

现在我们开始考虑状态转移方程。我们从金额为 1 开始,逐步计算到目标金额 11。

 

 

5.对于金额为 1,我们有以下选择:

 

6.使用面额为 1 的硬币,需要 1 枚硬币。

 dp[1] = min(dp[1], dp[1 - 1] + 1) = min(INF, dp[0] + 1) = min(INF, 0 + 1) = 1

 

7.对于金额为 2,我们有以下选择:

 

8.使用面额为 1 的硬币,需要 1 枚硬币。

9.使用面额为 2 的硬币,需要 1 枚硬币。

 dp[2] = min(dp[2], dp[2 - 1] + 1, dp[2 - 2] + 1) = min(INF, dp[1] + 1, dp[0] + 1) = min(INF, 1 + 1, 0 + 1) = 1

 

10.对于金额为 3,我们有以下选择:

 

11.使用面额为 1 的硬币,需要 1 枚硬币。

12.使用面额为 2 的硬币,需要 2 枚硬币。

 dp[3] = min(dp[3], dp[3 - 1] + 1, dp[3 - 2] + 1) = min(INF, dp[2] + 1, dp[1] + 1) = min(INF, 1 + 1, 1 + 1) = 2

 

13.对于金额为 4,我们有以下选择:

 

14.使用面额为 1 的硬币,需要 1 枚硬币。

15.使用面额为 2 的硬币,需要 2 枚硬币。

 dp[4] = min(dp[4], dp[4 - 1] + 1, dp[4 - 2] + 1) = min(INF, dp[3] + 1, dp[2] + 1) = min(INF, 2 + 1, 1 + 1) = 2

 

16.依次类推,我们可以计算出 dp[5]、dp[6]、dp[7]、dp[8]、dp[9]、dp[10]、dp[11]。

 

 

17.结果输出:

根据计算得到的 dp 数组,我们可以看到 dp[11] = 3,表示组成总金额 11 所需的最少硬币数为 3。

 

所以,对于给定面额为 [1, 2, 5] 的硬币和总金额 11,我们需要 3 枚硬币才能凑出总金额 11。

c++代码

#include <iostream>

#include <vector>

#include <climits>

 

using namespace std;

 

int coinChange(vector<int>& coins, int amount) {

    vector<int> dp(amount + 1, INT_MAX);

    dp[0] = 0; // 表示凑出金额为0的最小硬币数为0

    

    for (int i = 1; i <= amount; ++i) {

        for (int coin : coins) {

            if (i - coin >= 0 && dp[i - coin] != INT_MAX) {

                dp[i] = min(dp[i], dp[i - coin] + 1);

            }

        }

    }

    

    return dp[amount] == INT_MAX ? -1 : dp[amount];

}

 

int main() {

    vector<int> coins = {1, 2, 5};

    int amount = 11;

    cout << "最少硬币数: " << coinChange(coins, amount) << endl; // 输出:3

    return 0;

}

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值