最少找零问题与完全背包模型的一点思考
来源:互联网 发布:淘宝怎么实名认证激活 编辑:程序博客网 时间:2024/06/06 02:38
最少找零问题描述如下,有n张硬币,价值存储在一个数组中,每种硬币个数都是无限的,再给定一个要找的零钱数,然后试用最少的数目的硬币来找我们要求的数目。
比如 5,2,3,要找出20元钱,我们人工的判断几个可能,很快就可以找出最优,也就是4张5元,也就是4.
如果这个题目要求用程序解决,我们可以遵循如下思路
首先如果全部用5元,则其最多4张,如果全部用2元,则最多是10张,如果全部3元,最多6张(如果是7张,则大于20元),所以我们可以使用暴力递归来判断,在0张5元,0张2元,0张3元, 或者0张5元,0张2元,1张3元,或者0张5元,0张2元,2张3元·······
以钱币金额为标准,其调用的数目表格如下,
5 2 3
——————
0 0 0
0 0 1
0 0 2
0 0 3
0 0 4
0 0 5
0 0 6
0 1 0
0 1 1
0 1 2
0 1 3
0 1 4
0 1 5
0 1 6
0 2 0
0 2 1
0 2 2
0 2 3
0 2 4
0 2 5 (这里3元金额的数目为5,而没有到6,是因为前面调用了0张5元,2张2元,这是剩余金额为20-2*2=16元,最多需要5张)
0 3 0
··············
从以上表格可以看到在标注的地方,选择了0张5元,2张2元,5张3元,这时候还剩1元,这个需要我们考虑,如果多了1元,该如何处理。
如果做过背包问题的多重背包问题,必然知道这个题目的模型和多重背包是很类似的,一个深度搜索,在下标到达边界时候,返回一个值,但是多重背包返回的是0,而且多重背包完全不会考虑你装完最后一个物品后, 你的背包容量还剩几个单元,是正好装满,还是差几个单元,它只关注他的总体最大价值,而这个题和完全背包问题的区别在于,这个题需要判断,我们在递归到边界的时候,“背包”的容量还有多少,如果前面选择了x个5元,y个2元,z个3元,这时候再递归到边界时候,“背包”剩余容量是0,代表前面的这些组合正好组成了我们需要的金钱数目,这时候需要返回什么?同样如果前面选择了x个5元,y个2元,z个3元,这时候再递归到边界时候,“背包”剩余容量不是0,代表前面的组合没有组成我们要的数目,还差几块钱,这时候,要返回什么?
很明显,面对第一个问题,我们只需要返回0就可以了,然后前面的硬币数目(比如 x y z)加上返回值,就可以返回其组合数。
面对第二个问题,我们可以用一个例子来看看
5 2 3
——————
···········
0 4 0 -----> 要给前面返回一个比较大的值
0 4 1 -----> 要给前面返回一个比较大的值
0 4 2 -----> 要给前面返回一个比较大的值
0 4 3 -----> 要给前面返回一个比较大的值
0 4 4
0 5 0
0 5 1
0 5 2
上面是几组数据, 对于前四组,我们口算就可以得知其都不可以组合成20,递归到边界时候,要返回一个值,返回谁?如果是0,肯定是错误的,我们可以返回一个比较大的值,比如#define MAXSIZE 10010,返回这个MAXSIZE,往下走,在0 4 4 时候,正好可以组合成20元,返回0,然后0+4+4+0(相加顺序是从后往前的,因为递归本来就是从后往前回溯的)=8,对于0张5元,4张2元,我们可以得到5个返回值,分别是 MAXSIZE, MAXSIZE, MAXSIZE, MAXSIZE,8,我们找到这里面最小的8,就可以结束(0,4,x)这个递归了,后面也都是一样。
总结下,如果递归到边界时候,剩余硬币数目为0,也就是刚刚好,要返回0,如果是非0,则返回一个预定义的一个较大值,代码如下。
#include <iostream>#include <cstdlib>#include <cstdio>#include <cstring>using namespace std;#define MAXSIZE 10010int arr[100]={3,5};int fun(int arr[],int index,int aim){int ret=MAXSIZE; if(index==2) { if(aim==0)return 0;elsereturn MAXSIZE; } if(aim<=0) { return 0; } for(int i=0;i*arr[index]<=aim;i++) { ret=std::min(ret,i+fun(arr,index+1,aim-i*arr[index])); } return ret;}int main(){if(MAXSIZE==fun(arr,0,2)){ cout<<0<<endl;}elsecout<<fun(arr,0,22); return 0;}
- 最少找零问题与完全背包模型的一点思考
- 完全背包---找零问题
- 动态规划:最少硬币找零问题、01背包问题、完全背包问题
- 硬币找零问题(完全背包)
- 完全背包问题思考与学习
- [背包问题] 01背包、完全背包、整数找零
- 硬币找零 完全背包
- 硬币找零 完全背包
- 最少硬币找零问题
- 最少找零问题
- nyoj995硬币找零完全背包
- 硬币找零(完全背包)
- NYOJ995 硬币找零(完全背包)
- 背包问题 - 硬币找零
- 最少找零
- nyist 995 硬币找零(完全背包)
- nyist 硬币找零(完全背包)
- NYOJ 995 硬币找零(完全背包)
- 虚基类
- maryland上安装opencv
- 使用PHP生成二维码的两种方法(带logo图像)
- 机器学习算法总览——思维导图
- 数据库(sqlite3)项目实际应用
- 最少找零问题与完全背包模型的一点思考
- Letter Combinations of a Phone Number
- HDU 1085 母函数
- oc学习笔记-protocol代理模式
- 使用netstat检测及监测网络连接
- BFS与DFS
- 004.简单的加减乘除
- Cache工作原理
- XDebug