1、算法分析与设计实验指导书算法分析与设计实验指导书 姓名:_ 学号:_ 班级:_指导教师:_计算机科学与工程系编2012年9月6日使用本书前,请先阅读以下内容:本书是为配合算法分析与设计实验教学大纲而编写的上机指导,其目的是使学生消化理论知识,加深对讲授内容的理解,尤其是一些算法的实现及其应用,培养学生独立编程和调试程序的能力,使学生对算法的分析与设计有更深刻的认识。上机实验一般应包括以下几个步骤:(1)准备好上机所需的程序。手编程序应书写整齐,并经人工检查无误后才能上机。(2)上机输入和调试自己所编的程序。一人一组,独立上机调试,上机时出现的问题,最好独立解决。(3)上机结束后,整理出实验报告
2、。实验报告应包括:题目、程序清单、运行结果、对运行情况所作的分析。本书共分5个实验,其具体要求和步骤如下:实验一 递归与分治一、实验目的与要求1、掌握递归方法解决问题的一般技巧;2、熟悉二分搜索等算法;3、掌握分治算法思想;二、实验题1、设a0:n-1是一个已排好序的数组。请改写二分搜索算法,使得当搜索元素x不在数组中时,返回小于x的最大元素的位置i和大于x的最小元素位置j。当搜索元素在数组中时,i和j相同,均为x在数组中的位置。2、设有n个不同的整数排好序后存放于T0:n-1中,若存在一个下标i,0in,使得Ti=i,设计一个有效的算法找到这个下标。要求算法在最坏的情况下的计算时间为O(lo
3、gn)。3、 设计一个有效算法, 对于一个给定的数组循环左移i 位, 要求时间复杂度为O( n) ,辅助空间为O(1 )。例如对abcdefghijk 循环左移3位得到defghijkabc。4. 在一个序列有n个元素, 其中出现次数最多的元素称为众数。请设计算法寻找众数并分析算法的时间复杂性。(如果假设众数出现次数n/2,试找一个时间复杂度为o(n )的算法)三、实验提示1、用left,right, mid表示二分搜索算法的搜索区间的左端点,右端点和中间点,当搜索元素x在数组中时,返回找到的位置,当搜索元素x不在数组中时,返回left,right即可。要注意,当搜索元素比第一个元素小时,小于
4、x的最大元素不存在,当搜索元素比最后一个元素大时,大于x的最小元素不存在。2、用二分搜索算法即可实现。证明如下:3用三次逆转算法实现。1)用长度为n的数组保存字符串,将字符串进行划分,前i位看成一个子串,后n-i位看成一个子串。(分为两个子问题)上例:两个子串abc defghijk2) 用逆转算法分别将两子串反序。上例:abccba defghijk kjihgfed (逆转算法:头尾交换时,只用到一个辅助空间, 时间复杂度=两子串长度之和n)逆转算法结束后数组变成cbakjihgfed3) 将整个字符串再用逆转算法反序。cbakjihgfed defghijkabc (逆转算法:头尾交换时
5、,只用到一个辅助空间, 时间复杂度=字符串长度n)注:逆转算法可以写成通用函数。总之:时间复杂度为2n=O( n) ,辅助空间为O(1 ) 。4、可以选用一个时间复杂度O(nlogn)的排序算法(最好用分治算法)将数组排序,然后用O(n)时间来统计每个数的出现次数,从而求出众数。 假设众数出现次数n/2时,算法如下:1.数字两两比较,如果两者不同,则两个数都丢掉;否则,丢掉一个数留下另一个数。最后留下的数(加上未参与比较的数)中,原来的“众数”仍然是众数。(恰好进行了n/2次测试)2.如果存在一个数未参与比较,则用它和留下的数依次比较。如果一半或一半以上的比较都相同,则这个数就是众数(为什么?
6、反证法),找到众数,算法结束;否则这个数一定不是众数,丢掉它。(最多进行了n/2次测试)3.对留下的数中,自然“众数”占多数(为什么?)。重复步骤1至2直到只剩下一个数,这个数就是众数,算法结束。(可以用队列实现,留下的数入队)四、实验步骤1 理解算法思想和问题要求;2 编程实现题目要求;3 上机输入和调试自己所编的程序;4 验证分析实验结果;5 整理出实验报告。实验二 贪心算法一、实验目的与要求1、熟悉多机调度,汽车加油问题的算法;2、掌握贪心算法思想及步骤;二、实验题1、要求给出一种作业调度方案,使得所给的n个作业,尽可能短的时间内由m台机器加工处理完成。假设作业的编号为0n-1,加工时间
7、为t0 tn-1 , 机器编号为0m-1 ,每个作业均可在任何一台机器上加工处理,但未完工前不允许中断处理。作业不能拆分成更小的子作业。有如下输出格式要求。-作业个数:7机器台数:3作业 0 所需要的时间: 2作业 1 所需要的时间 14作业 2 所需要的时间 4作业 3 所需要的时间 16作业 4 所需要的时间 6作业 5 所需要的时间 5作业 6 所需要的时间 3机器 0 加工总时间 16 = 16机器 1 加工总时间 17 = 14 + 3机器 2 加工总时间 17 = 6 + 5 + 4 + 2机器 0 上的加工作业编号 3机器 1 上的加工作业编号 1 6机器 2 上的加工作业编号
8、4 5 2 0-2、一辆汽车加满油后可以行驶N千米。旅途中有若干个加油站。若要使沿途的加油次数最少,设计一个有效的算法,指出应在哪些加油站停靠加油。并证明你的算法能产生一个最优解。3、找零钱问题。设有m种钱币,编号1m,面值分别为c1,c2,c3,cm, 枚数分别为n1,n2,n3,nm,试用上述钱币来找出金额为t的零钱,使得所找零钱的枚数最小。如果没法找零钱,请打印“无解”。例如:面值为1角、2角、5角、1元、2元、5元、10元、20元、50元,100元各有1、1、1、1、1、4、3、1、2、5枚,分别零钱432.5元和345元。结果如下。请输入钱币种数:10请输入面额:0.1 枚数:1请输
9、入面额:0.2 枚数:1请输入面额:0.5 枚数:1请输入面额:1 枚数:1请输入面额:2 枚数:1请输入面额:5 枚数:4请输入面额:10 枚数:3请输入面额:20 枚数:1请输入面额:50 枚数:2请输入面额:100 枚数:5请输入要找的零钱数:432.5结果如下:面额0.1的枚数0枚面额0.2的枚数0枚面额0.5的枚数1枚面额1的枚数0枚面额2的枚数1枚面额5的枚数0枚面额10的枚数1枚面额20的枚数1枚面额50的枚数0枚面额100的枚数4枚总枚数:8枚还想要找其它零钱吗?(Y/N)Y请输入要找的零钱数:209结果如下:无解还想要找其它零钱吗?(Y/N)N三、实验提示1、采用处理时间最长
10、的作业优先加工的贪心策略。1)把作业按加工时间从大到小排序。(对作业编号按加工时间排序,得到一个加工顺序)2)每台机器上先按加工顺序分配一个作业,以后一旦有机器空闲,就按加工顺序分配一个作业到空闲机器上,直到所有作业加工完成。2、把两加油站的距离放在数组中,a1.n表示从起始位置开始跑,经过n个加油站,ak表示第k1个加油站到第k个加油站的距离。贪心策略:汽车在运行的过程中当前油量如果能跑到下一个站则不加油,否则要加满油。3、贪心策略:先找最大面值的,要是不够再找面值小一点的,直到找完为止。1)对钱币进行编号,对编号按面值从大到小排序,得到一个找钱顺序2)按找钱顺序进行,如果(剩余零钱/面值)
11、小于等于该面值的最大枚数,则要找的枚数为(剩余零钱/面值),否则要找的枚数为该面值的最大枚数。3)重新计算剩余零钱,再用面值小一点的钱币进行2)。 4)所有钱币试过后,如果还有零钱没有找,则没法找零钱(无解)。四、实验步骤1 理解算法思想和问题要求;2 编程实现题目要求;3 上机输入和调试自己所编的程序;4 验证分析实验结果;5 整理出实验报告。实验三 动态规划算法一、实验目的与要求1、 熟悉最长公共子序列问题的算法;2、 熟悉最大子段和,找零钱、最大k乘积问题的算法;3、掌握动态规划算法思想及步骤;二、实验题1、若给定序列X=x1,x2,xm,则另一序列Z=z1,z2,zk,是X的子序列是指
12、存在一个严格递增下标序列i1,i2,ik使得对于所有j=1,2,k有:zj=xij。例如,序列Z=B,C,D,B是序列X=A,B,C,B,D,A,B的子序列,相应的递增下标序列为2,3,5,7。给定2个序列X和Y,当另一序列Z既是X的子序列又是Y的子序列时,称Z是序列X和Y的公共子序列。给定2个序列X=x1,x2,xm和Y=y1,y2,yn,找出X和Y的最长公共子序列。 2、最大子段和问题。若给定n个整数组成的序列a1,a2,a3,an,求该序列sum=aiai1aj,的最大值。如果sum的最大值max 则 max=sum maxi=i maxj =j 时间复杂度O(n3) 2) 改进的穷举法
13、 设ai 到aj-1的和为sum 则ai到aj的和sum=sum+aj 请改进穷举算法, 求ai 到 aj的和时,充分利用已有结果:ai 到 aj-1的和。 时间复杂度可以降为O(n2)3) 分治法如果将所给的序列a1:n分为长度相等的两段a1:n/2和an/2+1:n,分别求出这两段的最大子段和,则a1:n的最大子段和有三种情形:A. a1:n的最大子段和与a1:n/2的最大子段和相同;(s1,maxi1,maxj1)B. a1:n的最大子段和与an/2+1:n的最大子段和相同;(s2,maxi2,maxj2)C. a1:n的最大子段和为下面的形式。子段横跨两段 ai+an/2+an/2+1
14、+aj 对于A、B这两种情形可递归求得。对于情形C,计算如下: sa= maxai+an/2 | 1=i=n/2,并记下sa取最大值时下标maxi3sb= maxan/2+1+aj | n/2+1=j=n,并记下sb取最大值时下标maxj3则s3=sa+sb即为C的最大值。A、B、C三个子段的最大者即为原问题的解。时间复杂度O(nlogn),请证明。3) 动态规划令bj= maxai+aj | 1=i0时bj=bj-1+aj,否则bj=aj。由此可得计算bj的递归式: b0=0 bj=maxbj-1+aj,aj,1jn。 b0、b1、bn 的最大者为原问题的解。请说明最优子结构性质,重叠子问题
15、,并说明时间复杂度为O(n)。3、找零钱问题 设原问题为:零钱为t,用面值分别为c1,c2,a3,cm, 枚数分别为n1,n2,n3,nm的钱币找零。原问题可分为两种情形:1) 用面额为cm的钱币找零。当t=cm 并且 nm0 时,先用面额为cm的钱币找1枚。剩下零钱为t-cm,再递归地用面值分别为c1,c2,a3,cm, 枚数分别为n1,n2,n3,nm-1的钱币找零钱。(子问题1)2)不用面额为cm的钱币找零。剩下零钱为t,递归地用面值分别为c1,a2,cm-1, 枚数分别为n1,n2,nm-1的钱币找零钱。(子问题2) 3)1)和2)的总钱币数较小者,为原问题的解。 可见原问题分解子问题
16、1和子问题2,并且和原问题的类型相同。 假设P(i,t)为用面值为c1,c2,a3,ci, 枚数分别为n1,n2,n3,ni的钱币找零钱t所得的最少枚数。 则得递归式:(表示无解)公式中用到(求余),对于实验二的例子,把面值和零钱扩大10倍,转化整数(角币)处理。对于下面例子,试用贪心算法和动态规划求解。贪心算法能得到最优解吗?为什么?面值为1元、6元、15元,有3、3、3枚,零钱18元。4、最大k乘积问题 设f(i,j)表示i位整数划分成j段后的最大j乘积(j=1f(i,j)=maxf(m, j-1)* value (j, i, m)| j-1=m=j , j1 其中,value(j, i,
17、 m) 表示第j段组成的i-m位数(从第m+1位到第i位)求出f(n,k)即可。如:求十进制整数4356798分成4段的最大4乘积分为下列情况: (1) 递归地求435679分为3段的最大3乘积,然后乘以8 (2) 递归地求43567 分为3段的最大3乘积,然后乘以98 (3) 递归地求4356 分为3段的最大3乘积,然后乘以798 (4) 递归地求435 分为3段的最大3乘积,然后乘以6798 (5) 递归地求43 分为3段的最大3乘积,然后乘以56798 (5)以后这种情况不存在,43无法分为3段。 (1)(2)(3)(4)的最大值即为原问题的解四、实验步骤1 理解算法思想和问题要求;2
18、编程实现题目要求;3 上机输入和调试自己所编的程序;4 验证分析实验结果;5 整理出实验报告。实验四 回溯算法一、实验目的与要求1、掌握符号三角形问题的算法;2、掌握01背包问题的回溯算法;3、理解并掌握回溯算法;二、实验题图1、下图是由14个“+”和14个“-”组成的符号三角形。2个同号下面都是“+”,2个异号下面都是“-”。 + + - + - + + - - - - +- + + + - - + + - - + - - - +在一般情况下,符号三角形的第一行有n个符号。符号三角形问题要求对于给定的n,计算有多少个不同的符号三角形,使其所含的“+”和“-”的个数相同。2、01背包问题:给定
19、n种物品和一背包。物品i的重量是wi,其价值为vi,背包的容量为C。问应如何选择装入背包的物品,使得装入背包中物品的总价值最大?三、实验提示1、符号三角形:解向量:用n元组x1:n表示符号三角形的第一行。 可行性约束函数:当前符号三角形所包含的“+”个数与“-”个数均不超过half=n*(n+1)/4 无解的判断:n*(n+1)/2为奇数(主程序中判断)/二维数组p存放符号“+” 或“-”/count计算减号个数 /t 第一行第t个符号/pjt =1 第j行的左边数起,第t个符号为”-“/pjt =0 第j行的左边数起,第t个符号为”+“if (counthalf)|(t*(t-1)/2-co
20、unthalf) return; /无解判断,减号或加号个数超过一半?if (tn) /第一行试探完毕,输出一个答案for (int i=0;i2;i+) /对加号和减号试探 p1t=i; /第一行第t个符号设为加号或减号 count+=i; /减号个数累加 for (int j=2;j=t;j+) /从第2行到第t行 pjt-j+1=pj-1t-j+1pj-1t-j+2; /从第j-1行决定第j行符号( 异或运算) count+=pjt-j+1; /减号个数累加 Backtrack(t+1); / 递归试探第一行第t+1个符号 for (int j=2;j=t;j+) count-=pjt-
21、j+1; /减号个数恢复原来的值, 进行回溯 count-=i; /减号个数恢复原来的值, 进行回溯 2、01背包问题:0-1背包问题是子集选取问题。0-1背包问题的解空间可用子集树表示。在搜索解空间树时,只要其左儿子结点是一个可行结点,搜索就进入左子树。当右子树中有可能包含最优解时,才进入右子树搜索,否则将右子树剪去。设cp是当前价值;bestp是当前最优价值。计算右子树中解的上界的更好方法是将剩余物品依其单位重量价值排序,然后依次装入物品,直至装不下时,再装入该物品的一部分而装满背包。由此得到右子树中解的上界b。 当cp+b = 1) /考察第k件物品 3.1 如果kn 得到一个可行解,如
22、果比当前最优解好,替换当前最优解,转3.43.2 若 childk=0 /处理左子树,物品放入背包若不超重 令xk=1, childk=1计算背包中物品重量cw=cw+wk和价值cp=cp+pk;k=k+1 转33.3 若childk=1 /处理右子树,物品不放入背包令xk=0,childk=2 计算上界函数cb, 若cbparent = parent; b-lchild = lchild; b-uprofit = up; b-profit = cp; b-weight = cw; b-level = level; return b; /向队列H中增加活结点pH-EnQueue(p); /入队 注意队列中元素为指针/队列的定义省略,包括 InitQueue, EnQueue, DeleteMaxNode-删除队列中优先级最大的结点(自己写)1 令down=0; 将队列初始化为空;2 生成一个结点,表示背包中无物品。放入队列中。(uprofit=0, level=0, parent=null,详见队列的结点定义)3从队列中取出优先级uprofit最大的结点放入p,3.1 如果是p的层次最大(level=n),则p是最优解,打印结果,结束。3.2 对结点p生成左孩子和右孩子结点 。如果物品放入背包不超重,则同时生成左右孩子,否则只生成右孩子。(左
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1