• 动态规划之最少硬币凑钱问题


    #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求解

  • 相关阅读:
    spring mvc配置完后实现下载功能
    表单中Readonly和Disabled的区别(转载)
    EL表达式中fn函数 (转载)
    Spring mvc中@RequestMapping 6个基本用法小结(转载)
    web开发,关于jsp的常见问题,重复提交,防止后退。
    JQuery页面加载
    解决 spring mvc 3.0 结合 hibernate3.2 使用<tx:annotation-driven>声明式事务无法提交的问题(转载)
    数据库设计原则(转载)
    dhtmlxTree介绍(转载)
    主键索引
  • 原文地址:https://www.cnblogs.com/lvlang/p/10586361.html
Copyright © 2020-2023  润新知