《算法设计与分析》实验报告班级计算机2011-3班姓名学号2013年12 月08 日目录实验一二分查找程序实现…………………………………………………………………01页实验二棋盘覆盖问题………………………………………………………………………04页实验三0-1背包问题的动态规划算法设计……………………………………………….07页实验四背包问题的贪心算法………………………………………………………………10页实验五最小重量机器设计问题(回溯法) (12)页实验六最小重量机器设计问题(分支限界法) (15)页指导教师对实验报告的评语成绩:指导教师签字:年月日算法分析与设计实验报告—二分搜索算法的实现一、实验目的建立算法复杂度的理论分析与实验分析的联系,深刻体会算法复杂度作为算法的好坏评价指标的本质含义。
二、实验要求1、用c/c++语言实现二分搜索算法。
2、通过随机产生有序递增数组的方法,测出二分查找算法平均意义下比较次数随问题规模的变化结果,并绘制曲线表示。
三、实验原理折半查找法也称为二分查找法,它充分利用了元素间的次序关系,采用分治策略,可在最坏的情况下用O(log n)完成搜索任务。
它的基本思想是,将n个元素分成个数大致相同的两半,取a[n/2]与欲查找的x作比较,如果x=a[n/2]则找到x,算法终止。
如果x<a[n/2],则我们只要在数组a的左半部继续搜索x(这里假设数组元素呈升序排列)。
如果x>a[n/2],则我们只要在数组a的右半部继续搜索x。
二分搜索法的应用极其广泛,而且它的思想易于理解。
四、实验过程(步骤)1、产生随机有序递增数组使用rand()函数产生随机数,并组织成有序数组, ; 为使每次产生的随机数不同使用随机数发生器的初始化函数srand(time(0))for ( int j=100; j <=1000; j+=100 ) {array[0]=10+rand()%15;for(int i=1; i<j; i++) {// 生成递增随机数列array[i]=array[i-1]+1+rand()%3+rand()%10;}产生要查找的数的下标suffix 为要搜索的元素下标int suffix = rand() % j;key 为要查找的数据int key = array[suffix];2、统计理论平均查找次数和实际平均查找次数float count=0.0 //平均实际查找次数根据二分查找的算法可得理论平均查找次数为O(log n);3、二分查找int BinarySearch( int b[], int key, int left, int right ) {while( left <= right ) {middle = ( left + right ) / 2;if (Key == b[middle]) {RowCount++;return middle;}else if ( key < b[middle] ) {right = middle - 1;RowCount++;}else {left = middle + 1;RowCount++;}}return -1; //没有找到}五、运行结果x:数组个数y:平均查找时间系列1:理论平均查找时间系列2:实际平均查找时间六、实验分析与讨论在试验中,遇到了如何产生随机数递增数组的问题,解决方法是采用rand()函数获得随机递增数组和要查找的数字下标。
采用随机化的数组,能够更加具有普遍性,更加能够证明算法的平均查找时间。
七、实验心得二分查找在搜索有序表时,效率比较高。
通过这次实验我对二分查找算法的认识又有了新的提高。
指导教师对实验报告的评语成绩:指导教师签字:年月日算法分析与设计实验报告—分治法解决棋盘覆盖问题一、实验目的建立算法复杂度的理论分析与实验分析的联系,深刻体会算法复杂度作为算法的好坏评价指标的本质含义。
二、实验要求1、用c++程序语言实现分治法解决棋盘覆盖问题。
2、分析算法的时间复杂度三、实验原理用分治策略,可以设计解决棋盘问题的一个简介算法。
当k>0时,可以将2^k *2^k棋盘分割为4个2^k-1 * 2^k-1子棋盘。
由棋盘覆盖问题得知,特殊方格必位于4个较小的子棋盘中,其余3个子棋盘中无特殊方格。
为了将3个无特殊方格的子棋盘转化为特殊棋盘可以将一个L型骨牌覆盖这3个较小棋盘的会合处,所以,这3个子棋盘上被L型覆盖的方格就成为给棋盘上的特殊方格,从而将原问题转化为4个较小规模的棋盘覆盖问题。
递归的使用这种分割,直至棋盘简化为1*1棋盘为止。
四、实验过程(步骤)1、数据说明:tr:棋盘上左上角方格的行号tc:棋盘上左上角方格的列号dr:特殊方格所在的行号dc:特殊方格所在的列号定义了全局变量tile,用于进行覆盖。
区分4种不同L类型的骨牌,初始值为0.Board[]数组用来表示棋盘2、函数说明ChessBoard函数实现了递归的将棋盘划分为子棋盘,并将棋盘进行覆盖。
main()函数用来进行输入棋盘的大小和特殊棋盘的位置。
使用memset(Board,0,sizeof(Board))将Board[]数组清零使用setw()函数控制输出格式五、运行结果六、实验分析与讨论设T(n)是算法ChessBoard覆盖一个2^k * 2^k棋盘所需要的时间,则从算法的分治策略可知,T(k)满足如下递归方程:O(1)k = 0T(k) = {4T(k-1)+O(1)k>0解得此递归方程可得T(k) = O(4^k)。
由于覆盖一个2^k *2^k棋盘所需的L型骨牌个数为(4^k —1)/3,故算法ChessBoard是一个在渐进意义下最优的算法七、实验心得通过这次试验,更多的了解了分治法解题的思路就是将大问题化为若干子问题,再依次解决子问题,最后获得问题的答案。
是我更加熟练地使用分治策略解决问题。
指导教师对实验报告的评语成绩:指导教师签字:年月日算法分析与设计实验报告——0-1背包问题的动态规划算法的实现一、实验目的建立算法复杂度的理论分析与实验分析的联系,深刻体会算法复杂度作为算法的好坏评价指标的本质含义。
二、实验要求1、用c++语言实现0-1背包问题的动态规划算法。
2、分析0—1背包问题动态规划算法的时间复杂度并提出优化建议。
三、实验原理动态规划算法的基本思想是将待求解的问题分解成若干相关不独立的子问题,先求解子问题,然后从这些子问题的解得到原问题的解。
用一个表存储已解决的子问题的答案,不管该问题是否被用到,只要被计算过,就存入表中。
这样我们就可以在多项式时间内在表中找到需要的已求得的答案,避免了大量的重复计算。
这就是动态规划算法的基本思想。
四、实验过程(步骤)1、最优解结构分析及递归式由于动态规划解决的问题多数有重叠子问题这个特点,为减少重复计算,对每一个子问题只解一次,将其不同阶段的不同状态保存在一个二维数组中。
设所给0-1背包问题的子问题的最优值为m(i,j),即m(i,j)是背包容量为j,可选择物品为i,i+1,…,n时0-1背包问题的最优值。
由0-1背包问题的最优子结构性质,可以建立计算m(i,j)的递归式如下。
此时背包容量为j,可选择物品为i。
此时在对xi作出决策之后,问题处于两种状态之一:(1)背包剩余容量是j,没产生任何效益;(2)剩余容量j-wi,效益值增长了vi ;2、数据说明:N:物品个数C:背包容量W[]:物品重量数组V[]:物品价值数组3、函数说明void Knapsack(int *v,int *w,int c,int n, int m[][C+1]) 计算所给出的0-1背包问题的最优解void Traceback(int m[][C+1],int *w,int c,int n,int *x)根据函数Knapsack()计算出的m[][]数组计算出最优解,并输出结果。
int min(int x,int y)比较大小并返回较小的值;int maxint x,int y)比较大小并返回较大的值;五、运行结果六、实验分析与讨论按上述算法Krapsack计算后,m[1][c]所给出要求的0-1背包问题的最优值。
相应的最优解可有函数Tracback()根据m[][]数组计算得出。
计算复杂性分析:从计算m(i,j)的递归式看出,函数Knapsack需要O(nc)计算出时间,函数Traceback 需要O(n)计算时间。
算法Knapsack有两个较明显的缺点。
其一是算法要求所给的物品的重量必须是整数,其次,当背包容量c很大时,算法需要的计算时间较多。
当c>2^n时,算法Knapsack需要Ω(n2^n)计算时间。
七、实验心得使用动态规划算法用于解0-1背包问题,比穷举法具有相当好的效率。
由于0-1背包的时间复杂度为O(2^n),所以是一个NP难问题,可以通过计算跳跃点的方式转变为计算复杂度为多项式时间内的算法,从而对算法进行了优化。
这次实验用到的是动态规划法,0-1背包问题用动态规划法首先要构造动态规划表,用三个for语句实现;根据动态规划表每行的最大值变化确定每个元素的装入与否,逐步确定出装入背包的物品,背包容量的最大值也就是动态规划表最右下角。
通过这次试验更加熟悉了动态规划算法的原理以及使用。
指导教师对实验报告的评语成绩:指导教师签字:年月日算法分析与设计实验报告——背包问题的贪心算法的实现一、实验目的建立算法复杂度的理论分析与实验分析的联系,深刻体会算法复杂度作为算法的好坏评价指标的本质含义。
二、实验要求1、用c++语言实现背包问题的贪心算法。
2、分析算法的计算复杂性并验证能否得到最优解三、实验原理贪心算法总是做出在当前看来是最好的选择。
贪心算法并不从整体最优上加以考虑,它总是做出的选择只是在某种意义上的局部最优选择。
贪心法解决背包问题的基本步骤:首先计算每种物品单位重量的价值v/w,然后,依贪心选择策略,将尽可能多的单位重量价值最高的物品装入背包。
若将这种物品全部装入背包后,背包内的物品总重量未超过才,则选择单位重量价值次高的物品并尽可能多的装入背包。
以此策略一直进行下去,直到背包装满为止。
五、实验过程(步骤)数据说明:N:物品数量c:背包容量V[]:物品价值数组m[]:物品重量数组x[]:物品放入背包的重量函数说明:V oid Knapsack(int n,float c,float w[],float x[]) 用来计算最大价值Sort(int n,float v[],float w[])用来计算单位重量价值的物品,并从大到小进行排序。
五、运行结果七、实验分析与讨论Knapsack算法的主要计算时间在于将个物品依其单位重量的价值从大到小排序。