426-动态规划算法-硬币选择问题

小咪咪 2022-09-05 04:24 313阅读 0赞

硬币选择问题

硬币选择问题:有1,3,5分面额的硬币,给定一个面值11,问组成给定面值所需要的最少的硬币数量是多少???

我们先用分治算法解决

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

递归版本的动态规划算法

我们知道:
在这里插入图片描述

  1. #include <iostream>
  2. #include <algorithm>
  3. using namespace std;
  4. //参数n表示面值, 返回值表示组成面值n所需要的最少的硬币数量
  5. const int n = 100;
  6. int dp[n + 1] = {
  7. 0 };//dp[n] : 组成价值n需要的硬币最少数量
  8. int cnt = 0;//代码测试
  9. int func1(int n)
  10. {
  11. if (dp[n] > 0)
  12. {
  13. //表示dp[n]这个子问题已经被求解过了
  14. cnt++;
  15. return dp[n];//直接返回就可以了
  16. }
  17. if (n == 1 || n == 3 || n == 5)
  18. {
  19. dp[n] = 1;//代表了一个子问题最优解的性质(或者说状态)
  20. return 1;
  21. }
  22. else if (n == 2 || n == 4)
  23. {
  24. dp[n] = 2;//代表了一个子问题最优解的性质(或者说状态)
  25. return 2;
  26. }
  27. else
  28. {
  29. int n1 = func1(n-1) + 1;//选择了1分硬币
  30. int n2 = func1(n-3) + 1;//选择了3分硬币
  31. int n3 = func1(n - 5) + 1;//选择了5分硬币
  32. dp[n] = std::min({
  33. n1, n2, n3 });
  34. return dp[n];//把子问题的状态记录在dp中
  35. //return std::min(std::min(n1, n2), n3);
  36. }
  37. }

在这里插入图片描述
如果使用分治算法,子问题被重复求解了186次

非递归版本的动态规划算法

在这里插入图片描述

  1. int main()
  2. {
  3. //非递归的动态规划算法如下:
  4. int v[] = {
  5. 1,3,5 };//硬币的面值
  6. int length = sizeof(v) / sizeof(v[0]);//硬币的个数
  7. int c = 18;
  8. int *dp = new int[c + 1]();//因为要访问dp[c] ,dp[0] = 0
  9. for (int i = 1; i <= c; ++i)
  10. {
  11. dp[i] = i;//表示初始化全部由1分硬币组成,这个选择的数量肯定是最多的
  12. for (int j = 0; j < length; ++j)//遍历硬币数组
  13. {
  14. if (i >= v[j] && (1 + dp[i - v[j]]) < dp[i])//面值大于等于硬币的面额 ,而且发现有更优的值
  15. {
  16. dp[i] = 1 + dp[i - v[j]];//更新最优值
  17. }
  18. }
  19. }
  20. cout << dp[c] << endl;
  21. delete[]dp;
  22. return 0;
  23. }

在这里插入图片描述

发表评论

表情:
评论列表 (有 0 条评论,313人围观)

还没有评论,来说两句吧...

相关阅读

    相关 动态规划硬币

    > 题目:几年教师节活动中,公司里为培训讲师提供了不同面值的饮料兑换券(每种面值数量不限),培训讲师可以领取兑换券去食堂兑换鲜榨果汁,要求兑换券和果汁必须等价,姜小虎想要兑换一

    相关 动态规划硬币问题

    凑硬币问题 假设有 1 元,3 元,5 元的硬币若干(无限),现在需要凑出 11 元,问如何组合才能使硬币的数量最少? 用数组d来存储当前每个面值可以对应的合成的最小