算法设计与分析P3-4.doc_第1页
算法设计与分析P3-4.doc_第2页
算法设计与分析P3-4.doc_第3页
算法设计与分析P3-4.doc_第4页
算法设计与分析P3-4.doc_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

问题描述设有n种不同面值的硬币,各硬币的面值存于数组T1:n中。现要用这些面值的硬币来找钱,可以实用的各种面值的硬币个数不限。(1)当只用硬币面值T1,T2,Ti时,可找出钱数j的最少硬币个数记为C(i,j)。若只用这些硬币面值,找不出钱数j时,记C(i,j)=。 给出C(i,j)的递归表达式及其初始条件。其中,1in,1jL.(2)设计一个动态规划算法,对于1jL,计算出所有的C(n,j).算法只允许使用一个长度为L的数组。用L和n作为变量表示算法的时间复杂性。(3)在C(n,j),1=j=L,已计算出的情况下,设计一个贪心算法,对任意钱数m=L,给出用最少硬币找钱m的方法。当C(n,m)时,算法的计算时间为O(n+C(n,m)。分析这个问题用动态规划来解,归结到动态规划上面就变成了无限背包问题。区别在于,现在我们需要求一个最少的硬币数而不是最大值。但是选择的情况也是相同的,即每次选择都可以选择任何一种硬币。 首先,找零钱问题具有最优子结构性质:兑换零钱问题的最优子结构表述:对于任意需要找的钱数j,一个利用Tn中的n个不同面值钱币进行兑换零钱的最佳方案为P(T(1),j),P(T(2),j),.,P(T(n),j),即此时的最少钱币个数C(n,j)=k=0nP(T(k),j)则P(T(2),j),.,P(T(n),j)一定是利用Tn中n个不同的面值钱币对钱数j=j-P(T(1),j)* T(1)进行兑换零钱的最佳方案。其次,找零钱问题具有重叠于问题性质:a)当n=1时,即只能用一种钱币兑换零钱,钱币的面值为T0,有 (2)根据分析建立正确的递归关系:复杂度:算法的时间复杂度主要取决于程序的两个循环,所以算法的时间复杂度为:O(n2);算法执行过程中引入了一个二维数组,随着输入规模的增大,所需要的空间复杂度为:O(n2)算法: #include #include using namespace std; #define MAX 20002 #define INF 9999999 #define min(a,b) (a)(b)?(b):(a) int T11,Coins11,n;/硬币面值数组T,可以使用的各种面值的硬币个数数组 Coins,n种不同面值的硬币 int cMAX;/数组c存放要找的最少硬币个数 int m; /要找的钱数m void init() int i; coutn; coutn输入硬币面值及其此面值硬币的个数:endl; for(i=0;iTiCoinsi; coutm; int main(int argc, char *argv) init(); for(int i=0;i=m;+i) ci=INF; c0=0; for(int i=0;in;+i) for(int j=1;j=Ti;-k) ck=min(ck,ck-Ti+1); if(cm!=INF) coutn最少硬币个数为:cmendl; else cout-1endl; return 0; 运行结果:时间复杂度:从上面算法可知,最优值cj的计算过程中,最外层为循环for(j=1;j1&flag=0)循环,而while(k1&flag=0)循环中又嵌套着三个并列的for循环。因此本算法最坏情况下的复杂度是O(L*2n);最好的情况当然是里面for循环的条件不满足而不执行,此时的复杂度为O(L*n)。其中:L表示需要兑换的零钱数,对于L来说,该值一般不是很大,对于钱币来说,L会小于100元,即10000分;n表示钱币的种类,n值一般不会很大如钱币总的有13种(从1分,2分,100元)。经过以上分析,如是最坏情况时的复杂度应为O(L*2n),则该值对于内存和运行速度较小的自动售货机等的应用前景则不会很好。但本算法中的递归结构在LTn时,有可见对于钱币j=L时,求c(n,j)时,并不要求对从1ij,的所有情况都要求c(n,i)+1,而是只求。其中:1kn。钱币一般只有13种左右,因此其效率大为上升。最坏的情况下需要执行而M小于100元即10000分,远大于n。本算法的动态规划算法的时间复杂性比该问题的一般动态规划算法的效率要好得多。该算法的时间复杂性是103数量级的对于应用于自动售货机等运行速度较慢的机器来说是不成问题的。贪心算法由贪心算法可知尽量用大面值的硬币组合来找钱,可以使使用的硬币最少。而贪心算法对最少硬币问题的解决总是可以得到最优解很好的近似解。例如:9分面值的硬币5枚,8分面值的硬币5枚,2分面值的硬币8枚,要找25分钱。设要找的钱为m,硬币种类为n,ti(0i=n)为硬币的面值,ci为可以使用的各种面值的硬币个数,ki为第i种面值的硬币可以使用的最多个数(ki=minm/ti,ci)(1)将硬币依面值大小排序982(2)按面值种类划分不同情况有多少种面值就划分多少种情况.每种情况的第一枚硬币面值各不一样,其后对剩余的硬币按面值从大到小排列.划分为三个情况:982,892,298。对应ki为:k0=3,k1=3,k2=8得到近似最优解群为9分1枚,8分2枚;9分1枚,8分1枚,2分4枚;9分1枚,2分8枚.算法优化1,在寻找最优组合过程中,有些情况可以不予考虑。比如上例中2982,在以小面值的硬币为第一个的情况中,在寻找最优组合时,会遇到两种情况:a、使用硬币个数要比以大面值的硬币(如9和8)为第一个的情况大得多。b、寻找到的组合与前面的情况有重复。完整程序代码如下:#include#include#includeintn,money;structctypeintvalue;intcoin;templatevoidmake2Darray(type*&x,introws,intcols)x=newtype*rows;for(inti=0;irows;i+)xi=newtypecols;voidswap(ctype&a,ctype&b)ctypetemp;temp=a;a=b;b=temp;intpartition(ctypearray,intp,intr)inti,j;ctypekey;i=p;j=r+1;key=arrayp;while(true)while(array+i.valuekey.value);if(i=j)break;swap(arrayi,arrayj);arrayp=arrayj;arrayj=key;returnj;voidquicksort(ctypearray,intp,intr)intq;if(pn;int*coins=newintn+1;ctype*T=newctypen+1;for(inti=1;iTi.value;inputTi.coin;inputmoney;quicksort(T,1,n);/*for(i=1;i=n;i+)coinsi=Ti.coin;*/intmax=0;for(i=1;i=n;i+) max+=Ti.coin;max+=10;int*min=newintmoney+1;min0=0;int*cnum;make2Darray(cnum,money+1,n+1);for(i=0;i=money;i+)for(intj=1;j=n;j+)cnumij=0;if(T1.value=1)min1=1;cnum11=1;elsemin1=max;intj=2;while(j=money)minj=max;i=1;while(i=Ti.value) intcoinumber=cnumj-Ti.valuei;coinumber+;if(

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论