最优硬币组合问题|豆包 MarsCode AI刷题

175 阅读3分钟

最优硬币组合问题是一个经典的组合数学问题,它涉及到如何有效地使用不同面值的硬币来组合出特定的金额。

问题描述

假设我们有一组不同面值的硬币,每种硬币的数量可能有限。我们的目标是找出所有可能的硬币组合,这些组合能够加和到某个特定的金额。进一步地,如果我们想要找到最优的组合(例如,使用的硬币数量最少),问题就变得更为复杂。

解法思路

  1. 动态规划:

• 定义一个数组dp,其中dp[i]表示金额为i时所需的最少硬币数量(如果无法组成金额i,则dp[i]可以设置为一个很大的数,如无穷大)。

• 初始化dp[0]=0,因为金额为0时不需要任何硬币。

• 对于每种硬币的面值coin和数量count,遍历所有可能的金额j(从coin到目标金额),并更新dp[j]为dp[j-coin]+1和dp[j]中的较小值(前提是j-coin是一个有效的金额,即dp[j-coin]不是无穷大)。

  1. 回溯法(用于找出具体的最优组合):

• 在动态规划的基础上,我们可以从目标金额开始,逐步减去最大的硬币面值(在不超过当前金额的前提下),并记录使用的硬币。

• 重复这个过程,直到金额减为0。

• 回溯过程中记录的硬币组合就是最优组合之一。

示例

假设我们有硬币面值[1,5,10],数量不限,目标金额是11。

  1. 使用动态规划计算最少硬币数量:

• 初始化dp数组为[0,1,2,3,4,5,6,7,8,9,10,11](这里暂时都设置为金额本身,表示尚未找到更优的组合)。

• 对于面值1的硬币,遍历所有金额并更新dp数组。

  • dp[1]=min(dp[1],dp[0]+1)=1

  • dp[2]=min(dp[2],dp[1]+1)=2

  • ...

  • dp[11]=min(dp[11],dp[10]+1)=11(这里其实没有变化,因为面值1的硬币对大于其面值的金额没有优化作用)。

• 对于面值5的硬币,再次遍历并更新。

  • dp[5]=min(dp[5],dp[0]+1)=1

  • dp[6]=min(dp[6],dp[1]+1)=2

  • dp[7]=min(dp[7],dp[2]+1)=3

  • ...

  • dp[11]=min(dp[11],dp[6]+1)=2(这里优化了,因为可以用两个面值5的硬币和一个面值1的硬币组成11,但最优解是用一个面值10和一个面值1的硬币,所以后面还会进一步优化)。

• 对于面值10的硬币,继续遍历并更新。

  • dp[10]=min(dp[10],dp[0]+1)=1

  • dp[11]=min(dp[11],dp[1]+1)=1(最终优化为最优解)。

2. 使用回溯法找出最优组合:

• 从11开始,选择不大于11的最大硬币面值10,记录并使用一个面值10的硬币。

• 剩余金额1,选择不大于1的最大硬币面值1,记录并使用一个面值1的硬币。

• 金额减为0,回溯结束。

*最优组合为[10,1]。

通过上述方法,我们可以有效地解决最优硬币组合问题。这个问题不仅在数学上有趣,而且在现实生活中也有广泛的应用,如货币兑换、自动售货机找零等场景。