最少找零问题与完全背包模型的一点思考
2015-10-01 16:18
405 查看
最少找零问题描述如下,有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 00 0 10 0 20 0 30 0 40 0 50 0 60 1 00 1 10 1 20 1 30 1 40 1 50 1 60 2 00 2 10 2 20 2 30 2 40 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 40 5 00 5 10 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;}
相关文章推荐
- systemd
- KVM下DHCP无法取得IP的问题
- Discuz X3.2 论坛搬家教程
- stitching.cpp鱼眼图像拼接融合 源码分析
- JAV实现跳台阶问题(《剑指offer》)
- BZOJ1025 SCOI2009游戏
- zw版【转发·台湾nvp系列Delphi例程】HALCON FillUpShape2
- 高等数理统计(一)
- linux ps命令
- c语言入门经典(第5版)
- 缓存着色技术(Cache Coloring)
- zw版【转发·台湾nvp系列Delphi例程】HALCON FillUpShape1
- zw版【转发·台湾nvp系列Delphi例程】HALCON DivImage2
- laravel authorize(授权)
- [总结]FFMPEG视音频编解码零基础学习方法
- Linux、Apache、Mysql、PHP(LAMP) -- 部署文档
- Objective-C的initialize和init
- Maven的功用所引发的哲学思想
- codeforces B. Cow Program (记忆化搜索)
- java 实现文件复制的两种方式