<p>首先我们思考一个问题,如何用最少的硬币凑够i元(i<11)?为什么要这么问呢?两个原因:1.当我们遇到一个大问题时,总是习惯把问题的规模变小,这样便于分析讨论。2.这个规模变小后的问题和原来的问题是同质的,除了规模变小,其它的都是一样的,本质上它还是同一个问题(规模变小后的问题其实是原问题的子问题)。</p><p>好了,让我们从最小的i开始吧。当i=0,即我们需要多少个硬币来凑够0元。由于1,3,5都大于0,即没有比0小的币值,因此凑够0元我们最少需要0个硬币。(这个分析很傻是不是?别着急,这个思路有利于我们理清动态规划究竟在做些什么。)这时候我们发现用一个标记来表示这句“凑够0元我们最少需要0个硬币。”会比较方便,如果一直用纯文字来表述,不出一会儿你就会觉得很绕了。那么,我们用d(i)=j来表示凑够i元最少需要j个硬币。于是我们已经得到了d(0)=0,表示凑够0元最小需要0个硬币。当i=1时,只有面值为1元的硬币可用,因此我们拿起一个面值为1的硬币,接下来只需要凑够0元即可,而这个是已经知道答案的,即d(0)=0。所以,d(1)=d(1-1)+1=d(0)+1=0+1=1。当i=2时,仍然只有面值为1的硬币可用,于是我拿起一个面值为1的硬币,接下来我只需要再凑够2-1=1元即可(记得要用最小的硬币数量),而这个答案也已经知道了。所以d(2)=d(2-1)+1=d(1)+1=1+1=2。一直到这里,你都可能会觉得,好无聊,感觉像做小学生的题目似的。因为我们一直都只能操作面值为1的硬币!耐心点,让我们看看i=3时的情况。当i=3时,我们能用的硬币就有两种了:1元的和3元的(5元的仍然没用,因为你需要凑的数目是3元!5元太多了亲)。既然能用的硬币有两种,我就有两种方案。如果我拿了一个1元的硬币,我的目标就变为了:凑够3-1=2元需要的最少硬币数量。即d(3)=d(3-1)+1=d(2)+1=2+1=3。这个方案说的是,我拿3个1元的硬币;第二种方案是我拿起一个3元的硬币,我的目标就变成:凑够3-3=0元需要的最少硬币数量。即d(3)=d(3-3)+1=d(0)+1=0+1=1.这个方案说的是,我拿1个3元的硬币。好了,这两种方案哪种更优呢?记得我们可是要用最少的硬币数量来凑够3元的。所以,选择d(3)=1,怎么来的呢?具体是这样得到的:d(3)=min{d(3-1)+1, d(3-3)+1}。</p><p>OK,码了这么多字讲具体的东西,让我们来点抽象的。从以上的文字中,我们要抽出动态规划里非常重要的两个概念:状态和状态转移方程。</p><p>上文中d(i)表示凑够i元需要的最少硬币数量,我们将它定义为该问题的”状态”,这个状态是怎么找出来的呢?我在另一篇文章<a target=_blank href="http://www.hawstein.com/posts/dp-knapsack.html">动态规划之背包问题(一)</a>中写过:根据子问题定义状态。你找到子问题,状态也就浮出水面了。最终我们要求解的问题,可以用这个状态来表示:d(11),即凑够11元最少需要多少个硬币。那状态转移方程是什么呢?既然我们用d(i)表示状态,那么状态转移方程自然包含d(i),上文中包含状态d(i)的方程是:d(3)=min{d(3-1)+1, d(3-3)+1}。没错,它就是状态转移方程,描述状态之间是如何转移的。当然,我们要对它抽象一下,</p><p>d(i)=min{ d(i-v<sub>j</sub>)+1 },其中i-v<sub>j</sub> >=0,v<sub>j</sub>表示第j个硬币的面值;</p>

#include <iostream>using namespace std;int coin[3] = { 5, 3, 1 };int func(int num)
{int *d = new int[num + 1];d[0] = 0;for (int i = 1; i <= num; ++i){d[i] = i;for (int j = 0; j < 3; ++j){if (coin[j] <= i && d[i - coin[j]] + 1 < d[i]){d[i] = d[i - coin[j]] + 1;}}}return d[num];
}int main()
{int n;while (cin >> n)cout << func(n) << endl;return 0;
}

递归:

#include <iostream>using namespace std;int coin[3] = { 5, 3, 1 };int func(int num)
{if (num == 0)return 0;for (int i = 0; i < 3; ++i){if (num == coin[i]){cout << coin[i] << ' ';return 1;}}for (int i = 0; i < 3; ++i){if (num - coin[i] >= 0){cout << coin[i] << ' ';return func(num - coin[i]) + 1;}}}int main()
{int n;while (cin >> n)cout << endl << func(n) << endl;return 0;
}

动态规划:如果我们有面值为1元、3元和5元的硬币若干枚,如何用最少的硬币凑够11元?相关推荐

  1. 问题:如果我们有面值为1元、3元和5元的硬币若干枚,如何用最少的硬币凑够11元?.md

    问题 如果我们有面值为1元.3元和5元的硬币若干枚,如何用最少的硬币凑够11元? 动态规划的本质是将原问题分解为同性质的若干相同子结构,在求解最优值的过程中将子结构的最优值记录到一个表中以避免有时会有 ...

  2. c语言用10元20元50元不超过50张,凑够1000元,输出所有换算方式

    在 C 语言中,你可以使用循环和分支语句来枚举所有可能的换算方式. 示例代码如下: #include <stdio.h>int main() {int i, j, k;for (i = 0 ...

  3. 动态规划,存在1元,3元,5元硬币若干,使用最少硬币构成n元

    题目描述:存在一元,三元,五元硬币若干,如何用最少的硬币凑够11元. 看到最少这个字眼,我们可以进行判断能否通过动态规划进行求解,经过分析可以发现我们可以把这个问题拆分成相等的子问题,因此是可以用动态 ...

  4. 假设市面上有4种面值 硬币,20元、10元、5元、1元。输入一个钱数,能够使用最少的硬币凑成这个钱数

    假设市面上有4种面值 硬币,20元.10元.5元.1元.输入一个钱数,能够使用最少的硬币凑成这个钱数. 编程思想:先看看能取出来几个20元的,在看看剩下的钱能取出来几个10元的,以此类推再取五元和一元 ...

  5. 用10元,20元,50元三种币值的纸币凑出1000元,一共有多少种组合(C++实现)三种思路,两种实现

    今天做了中金所的笔试题,被一道题卡住了.题目意思是: 用10元,20元,50元三种币值的纸币凑出1000元,一共有多少种组合? 当时一眼看上去分析了一下,以为是背包问题,类似于爬楼梯,于是直接带了爬楼 ...

  6. 动态规划--用最少的硬币类别找零钱

    #include<iostream> using namespace std;//coinNum[i]当前钱为i时需要的最少硬币数 void FindMin(int money,int * ...

  7. 【动态规划】【打卡105天】:剑指 Offer II 103. 最少的硬币数目

    1.题目描述 给定不同面额的硬币 coins 和一个总金额 amount.编写一个函数来计算可以凑成总金额所需的最少的硬币个数.如果没有任何一种硬币组合能组成总金额,返回 -1. 你可以认为每种硬币的 ...

  8. 10元权限gm游戏_游戏P图超能打!揭秘10年老本儿500元升级计划

    Hello大家好呀~在之前的<你问我答>栏目中,我们曾向大家征集了有关十年笔记本修复的种种问题.今天,我们特意请来了首席生活家@VitaminC爱摄影 为我们解答热心值友的问题,另外他还带 ...

  9. 【深度学习看手相】台湾学生获奖 AI 项目是科学还是伪科学? 搜狐科技 08-06 12:44 1新智元报道 来源: medium,facebook 编译:胡祥杰 张易 【新智元导读】本周日带来一个有

    [深度学习看手相]台湾学生获奖 AI 项目是科学还是伪科学? 搜狐科技 08-06 12:44 1新智元报道 来源: medium,facebook 编译:胡祥杰 张易 [新智元导读]本周日带来一个有 ...

最新文章

  1. java 快排和堆排序
  2. 可持久化线段树——主席树
  3. 在Unity实现游戏命令模式
  4. GARFIELD@09-11-2004
  5. 静态库的冲突 duplicate symbol
  6. ipad中的active失效?
  7. 联想服务器RD450 配置RAID5阵列图文方法
  8. 【PAT甲】1051 Pop Sequence (25分)判断出栈顺序的合法性
  9. Java 8 Stream
  10. 唐纳德 高德纳给年轻人的建议 Donald Knuth - My advice to young people
  11. 室内设计优美语句_关于室内设计的名言
  12. 通过python获取浏览器cookie
  13. 大学生学科竞赛管理系统/竞赛管理系统的设计与实现
  14. 银河麒麟操作系统常用问题及解决方法
  15. EXCEL区分两列名单中不重复的人,以及统计单列名单人员的重复次数
  16. Error response from daemon: Pool overlaps with other one on this address space
  17. ubuntu18.04下安装微信不能发图片和文件
  18. Linux中阶—远程接入sshsftp(八)
  19. 点、线、三角形(C++)
  20. 在微信H5网页中获取用户基本信息

热门文章

  1. tar 打包压缩解压命令
  2. 授权MySQL可以远程访问
  3. win10桌面图标变成白色的解决方法
  4. 恩智浦arm芯片Linux,基于ARM处理器的工业控制系列【恩智浦】
  5. fileitem方法_Common-FileUpload框架中的FileItem对象 | 学步园
  6. python网络爬虫经典项目
  7. 5( 预热)Pandas库的安装
  8. Java 跨域解决方案
  9. AutoCAD2007中禁用shift+鼠标中键进行三维旋转
  10. 高级算法梳理(三)XGB算法