zoukankan      html  css  js  c++  java
  • 动态规划之最少硬币凑钱问题

    #include <iostream>
    using namespace std;
    
    /**
    题目描述:如果我们有面值为1元、3元和5元的硬币若干枚,最少要用多少枚硬币凑够n元?
    */
    
    /**
    解题分析:
    (1)要算n元要多少个凑完[f(n)],那我分类嘛:
         1.首先拿一个1元的硬币,所以这个分类所需最少硬币数为f(n-1) + 1
    	 2.首先拿一个3元的硬币,这个分类所需最少硬币数为f(n-3) + 1
    	 3.首先拿一个5元的硬币,这个分类所需最少硬币数为f(n-5) + 1
    	 对着三种分类分别求其凑的硬币数,然后取最小值就是最终结果:
    	 result = min{ f(n-1)+1, f(n-3)+1, f(n-5)+1 };
    (2)然后就很容易了,就是递归,只要设置好递归结束的边界条件即可
    */
    
    int min(int a, int b, int c)
    {
    	int min = a;
    	if(b < min)
    		min = b;
    	if(c < min)
    		min = c;
    	return min;
    }
    
    //普通递归法/分治法
    int recursion(int n)
    {
    	if(n == 5 || n == 3 || n == 1)
    		return 1;
    	if(n == 4 || n == 2)
    		return 2;
    	if(n <= 0)
    		return 0;
    
    	//最优子结构
    	return min(recursion(n - 1) + 1,
    		       recursion(n - 3) + 1,
    			   recursion(n - 5) + 1);
    }
    
    /**
    事实上在《算法导论》一书中强调动态规划算法核心点在于两个:
    (1)最优子结构
    (2)重叠子问题
    上面只是满足了最优子结构,但是重叠的子问题重复计算了;
    把这部分效率也进行优化才能算是真正的动态规划算法,
    否则只是普通递归/分治法。
    */
    
    //避免重复计算子问题->将子问题的解保存下来
    int F[20]={0};
    int Dynamic_Programming(int n)
    {
    	if(n == 5 || n == 3 || n == 1)
    		return 1;
    	if(n == 4 || n == 2)
    		return 2;
    	if(n <= 0)
    		return 0;
    
    	if(F[n] != 0)//表明已经计算过该子问题
    		return F[n];
    	//记录子问题的解,然后才return
    	F[n] = min(Dynamic_Programming(n - 1) + 1,
    		       Dynamic_Programming(n - 3) + 1,
    			   Dynamic_Programming(n - 5) + 1);
    	return F[n];
    }
    
    int main()
    {
    	int n;
    	while(cin>>n)
    		cout<<"When n = "<<n<<" ,result is: "<<Dynamic_Programming(n)<<endl;
    
    	return 0;
    }
    /**
    示例输入输出:
    -1
    When n = -1 ,result is: 0
    0
    When n = 0 ,result is: 0
    1
    When n = 1 ,result is: 1
    2
    When n = 2 ,result is: 2
    3
    When n = 3 ,result is: 1
    4
    When n = 4 ,result is: 2
    5
    When n = 5 ,result is: 1
    6
    When n = 6 ,result is: 2
    7
    When n = 7 ,result is: 3
    8
    When n = 8 ,result is: 2
    9
    When n = 9 ,result is: 3
    10
    When n = 10 ,result is: 2
    11
    When n = 11 ,result is: 3
    */


    关于记录子问题的解从而避免重复计算,还可看动态规划的另一个简单例子:

    更高效的Fibonacci求解

  • 相关阅读:
    使用C#实现DHT磁力搜索的BT种子后端管理程序+数据库设计(开源)
    便携版WinSCP在命令行下同步文件夹
    ffmpeg (ffprobe)分析文件关键帧时间点
    sqlite删除数据或者表后,回收数据库文件大小
    ubuntu 20.04下 freeswitch 配合 fail2ban 防恶意访问
    ffmpeg使用nvenc编码的结论记录
    PC版跑跑卡丁车 故事模式 亚瑟传说章节 卡美洛庆典 2阶段 心灵之眼 攻略
    There was an error loading or playing the video
    Nvidia RTX Voice 启动报错修复方法
    火狐浏览器 关闭跨域限制
  • 原文地址:https://www.cnblogs.com/lvlang/p/10586361.html
Copyright © 2011-2022 走看看