1、算法部分作业答案1.1算法:是对特定问题求解步骤的一种描述,是指令的有限序列。 程序:当一个算法用某种程序设计语言来描述时,得到的就是程序,也就是说,程序是用某种程序设计语言对算法的具体实现. 算法有输入、输出、确定性、能行性和有限性等特征,当不具备有穷性时,只能叫做计算过程,而不能称之为算法,算法可以终止,而程序没有此限制。1.2程序证明和程序测试的目的各是什么? 程序证明是确认一个算法能正确无误的工作. 程序测试的目的是发现错误1-9 解: n!的递归定义: 求解n!的递归函数long Factorial (long n) if(n0) cout”error!”;exit(0);if(n=
2、0) return 1; else return n *Factorial (n-1);1-10 使用归纳法,证明上题所设计的计算n!的递归函数的正确性 证明(归纳法证明): (1)首先,如果n=0,那么程序执行if(n=0) return 1;返回1,算法显然正确;(2)假定函数Factorial对n1)能正确运行,那么,当n=k时,算法必定执行:else return k *Factorial (k-1);因为Factorial (k-1)正确,所以,当n=k时,程序运行正确综合以上两点,可得程序正确.证毕.2-1, 简述衡量一个算法的主要性能标准,说明算法的正确性与健壮性的关系 答: 衡
3、量一个算法的主要性能指标有:正确性,简单性,高效低存储,最优性 算法的正确性与健壮性的关系:所谓算法的正确性:是指在合法的输入下,算法应实现预先规定的功能和计算精度要求;所谓算法的健壮性,是指当输入不合法时,算法应该能按某种预定的方式做出适当的处理;正确的算法不一定的是健壮的,健壮的算法也不一定是完全正确的.正确性和健壮性是相互补充的.一个可靠的算法,要求能在正常情况下正确的工作,而在异常情况下,亦能做出适当处理.2-9(1)设计一个C/C+程序,实现一个n*m的矩阵转置,原矩阵与其转置矩阵保存在二维数组中.Void reverse(int *a,int *b,int n,int m) For
4、(int i=0;in;i+) For(int j=0;jm;j+) bji=aij;(2)使用全局变量count,改写矩阵转置程序,并运行修改后的程序以确定此程序所需的程序步 Void reverse(int *a,int *b,int n,int m,int &count) int i=0;count+;int j=0;count+; For(;in;i+) For(;jn0时,有5n2-8n+2=1时程序执行n *Factorial (n-1);此时T(n)= T(n-1)+1故: 替换法: T(0)=0,T(1)=1,T(2)=2- 总结得到:T(n)=n;归纳法证明:(1),当n=0
5、时,T(0)=0,结论成立;(2)假设当k=0有T(n)=n;成立. 迭代法: T(n)=T(n-1)+1 =(T(n-2)+1)+1=(T(n-3)+1)+1)+1=.=T(0)+1+1.+1(n个1)=n2-19 利用递归树计算递推方程 假设n=2k,那么,总共有logn+1(即k+1)层,非递归部分之和为n2+n2/21+n2/22+n2/2k=(1+1/2+1/22+1/23+1/2logn)n2 =2n2+2n=O(n2)5-8三分搜索算法的做法是:它先将待查元素X与n/3处的元素比较,然后将X与2n/3处的元素比较,比较的结果或者找到X,或者将围缩小到原来的n/3int Searc
6、h3(int a,int left,int right,int x) /*递归算法*/ int l,u; if(leftau) return Search3(a, u+1, right,x); else if(xal) return Search3(a, l+1, u-1,x); else return Search3(a, left, l-1,x); return -1;void main() int n,*a; int x,i; coutn; a=new intn; /动态数组 int location=-1; for(i=0;in;i+) ai=i+1; coutx; coutendlS
7、earch3(a, 0, n-1,x)endl;void main() /*非递归算法*/ int a15; int x,i; int location=-1; for(i=0;ix; i=0; int j=14,l,u; while(iau) i=u+1; else if(xal) j=l-1; else i=l+1; j=u-1; coutlocationaright) swap(a,left,right);if(left+1=right) return; int k=(right-left+1)/3;stoogesort(a,left,right-k);stoogesort(a,left
8、+k,right);stoogesort(a,left,right-k);证明: 元素个数n=right-left+1; (1) 若为空表或只有一个元素(n=1时,即left+1=right)时,程序执行if(aleftaright) swap(a,left,right);之后,执行if(left+1=right) return;即此时程序做了一次元素之间的比较之后,不做任何操作,显然正确.(2) 假设当n=2)时,算确,即对于所有元素个数小于n的元素集,算法能正确排序.那么,当n= right-left+1时,算法执行程序段:int k=(right-left+1)/3;stoogesort
9、(a,left,right-k);stoogesort(a,left+k,right); stoogesort(a,left,right-k);由假设可知:以上三条语句都能正确运行,所以,当n= right-left+1时,算确. 由以上两点可知,算确. 分析算法的时间复杂度: 排序算法,基本运算仍然是元素之间的比较,所以,算法时间复杂度为: (用替换或迭代法计算之即可)6-1设有背包问题实例,n=7,(w0,w1,w2,w3,w4,w5,w6)=(2,3,5,7,1,4,1),(p0,p1,p2,p3,p4,p5,p6)=( 10,5,15,7,6,18,3),M=15。求这一实例的最优解及
10、最大收益.解:首先,选择最优量度标准为收益重量比;其次, 依据收益重量比的非增次序对输入(物品)进行排序 (p0/w0,p1/w1,p2/w2,p3/w3,p4/w4,p5/w5,p6/w6)=(5,5/3,3,1,6,4.5,3) 对物品排序结果为:4,0,5,2,6,1,3最后,进行贪心选择: X=(4) X=(4,0) X=(4,0,5) (剩余载重)U=14 U=12 U=8 (收益) P=6 P=6+10=16 P=16+18=34 X=(4,0,5,2) X=(4,0,5,2,6) X=(4,0,5,2,6,1(2/3) (剩余载重)U=3 U=2 U=0 (收益) P=34+15
11、=49 P=49+3=52 P=52+2/3*5=55.33所以,最优解为x=(1,2/3,1,0,1,1,1); 即装入第0,2,4,5,6物品和第1个物品的2/3 最大收益: P=55.336-2,0/1背包问题是一种特殊的背包问题,装入背包的物品不能分割,只允许或者整个物品装入背包,或者不装入,即xi=0,或1,(0=in),以题6-1的数据作为0/1背包的实例,按贪婪法求解,这样求得的解一定是最优解吗?为什么?解:首先,选择最优量度标准为收益重量比;其次, 依据收益重量比的非增次序对输入(物品)进行排序 (p0/w0,p1/w1,p2/w2,p3/w3,p4/w4,p5/w5,p6/w
12、6)=(5,5/3,3,1,6,4.5,3) 对物品排序结果为:4,0,5,2,6,1,3最后,进行贪心选择: X=(4) X=(4,0) X=(4,0,5) (剩余载重)U=14 U=12 U=8 (收益) P=6 P=6+10=16 P=16+18=34 X=(4,0,5,2) X=(4,0,5,2,6) X=(4,0,5,2,6) (剩余载重)U=3 U=2 继续考察第1和第3个 (收益) P=34+15=49 P=49+3=52 物品,都不能装入.所以,贪心法求得的0/1背包问题的最优解为x=(1,0,1,0,1,1,1);即装入第0,2,4,5,6物品 最大收益: P=52 但实际上
13、,当y=(1,1,1,0,1,1,0) 即装入第0,1,2,4,5物品,可获收益为P=54,所以,贪心法求得的0/1背包问题的解x一定不是最优解. 原因是: 对于0/1背包问题,贪心法并不能保证使其单位载重下的收益最大,因为通常在背包没还装满时,却再也装不下任何物品,这样,就使得单位载重下的物品收益减少,所以, 0/1背包问题通常不能用贪心法求解.6-3 设有带时限的作业排序实例n=7,收益(p0, p1, p2, p3, p4, p5, p6)=(3,5,20,18,1,6,30),作业的时限(d0, d1, d2, d3, d4, d5, d6)=(1,3,4,3,2,1,2),给出以此实
14、例为输入,执行函数JS得到的用最优解和最大收益。解:X=5,6,3,2 最大收益为74函数JS如下:int JS(int *d, int *x, int n) /设p0p1pn-1 int k=0; x0=0; for (int j=1; j=0 & dxrdj & dxrr+1)r-; /搜索作业j的插入位置 if(r0 | dxrr+1) /若条件不满足,选下一个作业 for (int i=k; i=r+1; i-) xi+1=xi; /将xr以后的作业后移 xr+1=j; k+; /将作业j插入r+1处 return k; 在执行JS函数之前,必须先对输入(即作业)按作业的收益非增次序排
15、序,结果为: 6,2,3,5,1,0,4X: 接着执行JS函数: 最初, 解集合X为空.6X:0 1 2 3 4 5 6 首先, 考虑作业6, 假设将其加入集合X, 即x0=6;考虑X中的作业能否均如期完成,因为此时X中只有作业6,其截止时限为2,故,能如期完成,此时,将作业6加入作业子集X中,此时,子集X中的最大可用下标k=0;X:6 接着,考虑作业2. 首先搜索作业2在X集合中的插入位置,使得X集合中的元素按作业的截止时限的非减次序排序,因为d6=2,而d2=4,所以,可将作业2插在作业6的后面,即x1=2,得到X=(6,2),X:62 考虑X中的作业能否均如期完成?因为d6=2=1, d
16、2=4=2,所以,X中作业均能如期完成,将作业2加入子集X中. 子集X中的最大可用下标k=k+1=1X:62考虑作业3.首先搜索作业3在X集合中的插入位置,使得X集合中的元素按作业的截止时限的非减次序排序,因为d6=2, d2=4,而d3=3所以,可将作业3插在作业6的后面,作业2的前面,得到X=(6,3,2),X:632 考虑X中的作业能否均如期完成?因为d6=2=1, d3=3=2, d2=4=3所以,X中作业均能如期完成,将作业2加入子集X中. 子集X中的最大可用下标k=k+1=2X:632考虑作业5.首先搜索作业5在X集合中的插入位置,使得X集合中的元素按作业的截止时限的非减次序排序,
17、因为d6=2, d2=4, d3=3而d5=1所以,可将作业5插在作业6的前面,得到X=(5,6,3,2),X:5632 考虑X中的作业能否均如期完成?因为d5=1=1,d6=2=2, d3=3=3, d2=4=4所以,X中作业均能如期完成,将作业5加入子集X中. 子集X中的最大可用下标k=k+1=3X:5632考虑作业1.首先搜索作业1在X集合中的插入位置,使得X集合中的元素按作业的截止时限的非减次序排序,因为d5=1,d6=2, d3=3,d2=4,而d1=3所以,可将作业1插在作业2的前面,作业3的后面,得到X=(5,6,3,1,2),X:56312 考虑X中的作业能否均如期完成?因为d
18、5=1=1,d6=2=2, d3=3=3, d1=34所以,X中1作业不能如期完成,所以,不能将作业1加入子集X. X:56320 1 2 3 4 5 6 k 接着考虑作业0,4均不能加入子集X,故,执行JS得到的最优解为X=(5,6,3,2),最大收益为P=p5+p6+p3+p2=30+20+18+6=746-17,最佳装载问题是将一批集装箱装上一艘载重为C的轮船,其中集装箱i的重量为wi(0=i0, wi0求X=()使得并且使最大 (2)以重量作为最优量度标准,以重量最轻者先装来选择集装箱装上船(3)设(x0,x1,-xn-1)是最优装载问题的最优解,则易知(x1,x2,-xn-1)是轮船
19、载重为C-x0w0且待装船的集装箱为1,3-n-1时相应最优装载问题的一个最优解,即最优装载问题具有最优子结构特性。否则,假设(x1,x2,-xn-1)不是子问题的最优解,假设有另一个解Z=(z1, z 2,- z n-1)是子问题的最优解,则有:则:且,即(x0,z1, z 2,- z n-1)是最优装载问题的最优解,与(x0,x1,-xn-1)是最优装载问题的最优解矛盾,所以, (x1,x2,-xn-1)是子问题的最优解,故最优装载问题具有最优子结构特性。(4) 参考程序1 /*箱子信息结构体*/struct goodinfo float w; /*箱子重量*/ int X; /*箱子存放
20、的状态*/ int flag; /*箱子编号*/;/*按物品重量做升序排列*/void sort(goodinfo goods,int n) int j,i; for(j=2;j=n;j+) goods0=goodsj; i=j-1; while (goods0.wgoodsi.w) goodsi+1=goodsi; i-; goodsi+1=goods0; /*用贪心法对物品进行选择装入*/void loading(goodinfo goods,float M,int n) float cu; int i,j; int A=0;/*对装入箱子进行计数*/ for(i=1;i=n;i+)/*赋
21、初值*/ goodsi.X=0; cu=M; /*船的剩余载重*/ for(i=1;icu)/*当该箱重量大于剩余载重跳出*/ break; goodsi.X=1; A+; cu=cu-goodsi.w;/*确定船的剩余载重*/ for(j=2;j=n;j+)/*对箱子按序号大小作升序排列*/ goods0=goodsj; i=j-1; while (goods0.flaggoodsi.flag) goodsi+1=goodsi; i-; goodsi+1=goods0; cout 最优解为:endl;/*输出*/ for(i=1;i=n;i+) cout 第i件物的存放状态:; coutgo
22、odsi.Xendl; coutendl; coutendl; cout 最多能装入的箱子数为:; coutAendl;(5) 首先,选择最优量度标准为重量;其次, 依据集装箱重量的非减次序对输入(物品)进行排序 对集装箱的排序结果为:5,2,0,3,1,4,6最后,进行贪心选择: X=(5) X=(5,2) X=(5,2,0) (剩余载重)U=24 U=21 U=17 X=(5,2,0,3) X=(5,2,0,3,1) X=(5,2,0,3,1) (剩余载重)U=12 U=6 所以,最优解为 X=(0,1,2,3, 5),最优解值为5参考程序2 public static float loa
23、ding(float c, float w, int x) int n=w.length; Element d = new Element n; for (int i = 0; i n; i+) di = new Element(wi,i); MergeSort.mergeSort(d); float opt=0; for (int i = 0; i n; i+) xi = 0; for (int i = 0; i n & di.w = c; i+) xdi.i = 1; opt+=di.w; c -= di.w; return opt; 7-5设有4 个矩阵连乘积ABCD:A: 45*8,
24、B: 8*40, C: 40*25, D: 25*10, ,请求出它们的最优计算次序和计算量。解:p0=45,p1=8,p2=40,p3=25,p4=10 可只给出矩阵形式计算m矩阵为: m01= p0*p1* p2=45*8*40=14400;m12= p1*p2* p3=8*40*25=8000;m23= p2*p3* p4=40*25*10=11250; m02= m00+m12+p0*p1* p3=8000+45*8*25=8000+9000=17000= m01+m22+p0*p2* p3=14400+45*40*25=14400+45000m13= m11+m23+p1*p2* p4=11250+8*40*10=11250+3200=
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1