《算法设计与分析》
实验报告
班级
姓名
学号
年 月 日
目录
实验一 二分查找程序实现…………………………………………………………………03页
实验二 棋盘覆盖问题(分治法).…………………………………………………………08页
实验三 0-1背包问题的动态规划算法设计……………………………………………….11页
实验四 背包问题的贪心算法………………………………………………………………14页
实验五 最小重量机器设计问题(回溯法)………………………………………………17页
实验六 最小重量机器设计问题(分支限界法)…………………………………………20页
指导教师对实验报告的评语
成绩:
指导教师签字:
年 月 日
实验一:二分查找程序实现
一、实验时间:20##年10月8日,星期二,第一、二节地点:J13#328
二、实验目的及要求
目的:
建立算法复杂度的理论分析与实验分析的联系,深刻体会算法复杂度作为算法的好坏评价指标的本质含义。
要求:
1、用c/c++语言实现二分搜索算法。
2、通过随机产生有序表的方法,测出在平均意义下算法比较次数随问题规模的变化曲线,并作图。
三、实验环境
平台:Win7 32位操作系统
开发工具:Codeblocks10.05
四、实验内容
对已经排好序的n个元素a[0:n-1],现在要在这n个元素中找出一特定元素x。
五、算法描述及实验步骤
算法描述:
折半查找法也称为二分查找法,它充分利用了元素间的次序关系,采用分治策略,可在最坏的情况下用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、首先设定问题规模n;
2、随即产生递增数列;
3、在n个有序数中随机取一个作为待查找量,搜索之;
4、记录查找过程中的比较次数,再次生成新的有序表并查找,记录查找次数,每个数组重复10次;
5、改变问题规模n重复上述步骤2~4,n取100、200……1000;
6、依实验数据作图,并与理论图作比较;
7、二分搜索算法平均查找次数:
问题规模为n时,平均查找次数为:
A(n)=Int(logn) + 1/2
// Int() 函数为向下取整
即二分搜索算法对于含有n个数据的有序表L平均作了约Int(logn)+1/2次的查找操作。
实验步骤:
1.初始化生成递增随机数列:
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;
}
}
2. 定义二分查找算法:
int BinarySearch( const int b[], int searchKey, int low, int high );
其中,返回值为int类型,数组b[]为待查递增序列,searchKey为所查数据,low为数组b[]左下标,hight为数组b[]右下标。
该算法实现过程为:
将数组b[]的n个元素分成个数大致相同的两半,取b[n/2]与searchKey作比较。如果searchKey=b[n/2],则找到searchKey,算法终止;如果searchKey<b[n/2],则只要在数组b的左半部继续搜索searchKey;如果searchKey>b[n/2],则只要在数组b的右半部继续搜索searchKey。
3.实现主函数并完成所有代码。
4.算法复杂性分析:
容易看出,没执行一次算法的while循环,待搜索数组的大小减少一半。因此,在最坏情况下,while循环被执行了O(logn)次。循环体内运算需要O(1)时间,因此整个算法在最坏情况下的计算时间复杂性为O(logn)。
六、调试过程及实验结果
输出结果为:
Every array repeat search times: 10
Number of Elements 理论平均查找次数 实际平均查找次数
100 6.5 6.1
200 7.5 7.3
300 8.5 7.4
400 8.5 7.4
500 8.5 7.5
600 9.5 8.2
700 9.5 8.8
800 9 .5 8.7
900 9.5 8.8
1000 9.5 9.4
七、总结
二分查找在搜索有序表时,效率比较高。通过这次实验我对二分查找算法的认识又有了新的提高。本想写个图形界面,但由于种种原因,没有实现,下次做加密算法时,要写一个图形化界面。
指导教师对实验报告的评语
成绩:
指导教师签字:
年 月 日
实验二:分治法解决棋盘问题
一、实验时间:20##年10月22日,星期二,第一、二节地点:J13#328
二、实验目的及要求
1、 用c/c++语言实现分治法解决棋盘问题算法。
2、 实现棋盘化以及棋盘覆盖
三、实验环境
Windows 20## 操作系统 以及code blocks软件
四、实验内容
在一个2^k*2^k的方格组成的棋盘中,若恰有一个方格与其他方格不同,则称该方格为一个特殊方格。用分治法将整个棋盘除特殊方格以外的方格覆盖。
五、算法描述及实验步骤
将2^k x 2^k的棋盘,先分成相等的四块子棋盘,其中特殊方格位于四个中的一个,构造剩下没特殊方格三个子棋盘,将他们中的也假一个方格设为特殊方格。如果是:
左上的子棋盘(若不存在特殊方格)----则将该子棋盘右下角的那个方格假设为特殊方格
右上的子棋盘(若不存在特殊方格)----则将该子棋盘左下角的那个方格假设为特殊方格
左下的子棋盘(若不存在特殊方格)----则将该子棋盘右上角的那个方格假设为特殊方格
右下的子棋盘(若不存在特殊方格)----则将该子棋盘左上角的那个方格假设为特殊方格
当然上面四种,只可能且必定只有三个成立,那三个假设的特殊方格刚好构成一个L型骨架,我们可以给它们作上相同的标记。这样四个子棋盘就分别都和原来的大棋盘类似,我们就可以用递归算法解决。
六、调试过程及实验结果
七、总结
由于覆盖一个2k*2k棋盘所需的L型骨牌个数为(4k-1)/3,故此算法是一个在渐近意义下最优的算法。
指导教师对实验报告的评语
成绩:
指导教师签字:
年 月 日
实验三:0-1背包问题的动态规划算法设计
一、实验目的及要求
1.了解并掌握动态规划算法的设计思想。
2.利用动态规划算法的设计思想实现0-1背包问题的算法设计。
二、实验环境
使用C++语言;
在windows环境下使用CodeBlocks调试并运行。
三、实验内容
1.了解并掌握动态规划的设计思想。
2.利用动态规划算法的思想解决0-1背包问题。
四、算法描述及实验步骤
每种物品一件,可以选择放1或不放0。
用子问题定义状态:即f[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值。则其状态转移方程便是:
f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]}
“将前i件物品放入容量为v的背包中”这个子问题,若只考虑第i件物品的策略(放或不放),那么就可以转化为一个只牵扯前i-1件物品的问题。如果不放第i件物品,那么问题就转化为“前i-1件物品放入容量为v的背包中”,价值为f[i-1][v];如果放第i件物品,那么问题就转化为“前i-1件物品放入剩下的容量为v-c[i]的背包中”,此时能获得的最大价值就是f[i-1][v-c[i]]再加上通过放入第i件物品获得的价值w[i]。
五、调试过程及实验结果
六、总结
0-1背包问题是最基本的背包问题,它包含了背包问题中设计状态、方程的最基本思想,另外,别的类型的背包问题往往也可以转换成0-1背包问题求解。通过这次实验我对动态规划算法的认识又有了新的提高。
指导教师对实验报告的评语
成绩:
指导教师签字:
年 月 日
实验四:背包问题的贪心算法
一、实验目的:
运用贪心算法思想,设计解决上述问题的算法,找出最大背包价值的装法。
二、实验要求
1. 用c++语言实现背包问题的贪心算法。
2.掌握贪心思想的应用。
三、实验原理
在贪心算法中采用逐步构造最优解的办法,在每个阶段,都做出一个看上去最优的决策(在一定的标准下 ),决策一旦做出就不可更改。
四、实验过程(步骤)
1. 定义背包结构体:
struct stone
{ int name;
int weight;//物品的剩余重量
int weight_t;//物品的重量
float benefit;//物品的价值
//float b;
};
2. 定义函数void sort(stone *data,int num) //计算物品的单位重量的价值,并进行排序
3. 定义主函数并完成贪心选择。
4.分析算法复杂性分析:
该算法的主要计算时间在于将各种物品依其单位重量的价值从大到小排序。因此,算法的计算时间上界为O(n*logn)。
与0-1背包问题类似,所不同的是在选择物品i装入背包时 ,可以选择物品i的一部分,可以选择物品i 可以选择物品 的一部分,而不一定要全部装入背包, 1≤i≤n。 这2类问题都具有最优子结构 ,最优子结构性质,极为相似,但 最优子结构 背包问题可以用贪心算法求解,而0-1背包问题却不能用贪心算法求解。
五、运行结果
六、实验分析与讨论
贪心法的基本思路:
——从问题的某一个初始解出发逐步逼近给定的目标,以尽可能快的地求得更好的解。当达到某算法中的某一步不能再继续前进时,算法停止。
该算法存在问题:
1. 不能保证求得的最后解是最佳的;
2. 不能用来求最大或最小解问题;
3. 只能求满足某些约束条件的可行解的范围。
实现该算法的过程:
1.Begin 从问题的某一初始解出发;
2.while 能朝给定总目标前进一步 do
3.求出可行解的一个解元素;
4.由所有解元素组合成问题的一个可行解
七、实验心得
贪心算法通过一系列的选择来得知问题的解,它所做的每一个选择都是当前状态下局部最好选择,即贪心选择。通过背包问题的解决,进一步掌握了贪心算法的思想,并能在解问题时灵活运用。
指导教师对实验报告的评语
成绩:
指导教师签字:
年 月 日
实验五:最小重量机器设计问题(回溯法)
一、 实验目的
建立算法复杂度的理论分析与实验分析的联系,深刻体会算法复杂度作为算法的好坏评价指标的本质含义。
二、 实验要求
1、 用c++语言实现最小重量机器设计的回溯算法。
2、 分析算法的计算复杂性
三、 实验原理
首先,应该明确的确定问题的解空间。确定了解空间的组织结构后,发从开始节点(根节点)出发,以深度优先方式搜索整个解空间。这个开始结点成为活结点,同时也成为当前的扩展结点。在当前的扩展结点处,向纵深方向搜索移至一个新的结点。这个新结点成为新的活结点,并成为新的扩展结点。如果在当前的扩展结点处不能再向纵深方向移动,则当前扩展结点成为死结点。此时,应往回移动(回溯)至最近的活结点,并使这个活结点成为当前的扩展结点。回溯以这种工作方式递归的在解空间中搜索,直至找到所要求的解或解空间中已无活结点为止。
四、 实验过程(步骤)
由于题目已经给出总价格的上限,因此算法通过使用回溯来选择合适的机器使得在总价格不超过d时得到的机器重量最小。首先初始化当前价格cp=0,当前重量cw=0,此外,还要设置一个变量sum表示选择机器的总重量,初始化其为每个部件从1号供应商购买的重量。在循环选择i号机器时,判断从j号供应商购买机器后的价格是否大于总价格,如果不大于则选择,否则不选,继续选择下一供应商进行判断。在得到一个合适的供应商后,继续选择下一机器的供应商,从第一个选到最后一个供应商。当所有机器选择结束后,判断得到的总重量是否比之前的sum小,如果小就赋给sum,然后从这一步开始,回溯到上一机器,选择下一合适供应商,继续搜索可行解,直到将整个排列树搜索完毕。这样,最终得到的sum即为最优解。
数据说明:
N:零件数量 m:不同的零件商
W[][]:是从供应商j处购得的部件i的重量 c[][]:相应的价值
算法设计:
a.部件有n个,供应商有m个,分别用w[i][j]和c[i][j]存储从供应商j 处购得的部件i的重量和相应价格,d为总价格的上限。
b.用递归函数backtrack(i)来实现回溯法搜索排列树(形式参数i表示递归深度)。
① 若cp>d,则为不可行解,剪去相应子树,返回到i-1层继续执行。
② 若cw>=sum,则不是最优解,剪去相应子树,返回到i-1层继续执行。
③ 若i>n,则算法搜索到一个叶结点,用sum对最优解进行记录,返回到i-1层继续执行;
④ 用for循环对部件i从m个不同的供应商购得的情况进行选择(1≤j≤m)。
c.主函数调用一次Knapsack(1)即可完成整个回溯搜索过程,最终得到的sum即为所求最小总重量。
五、 运行结果
六、实验心得
通过这次试验我明白了回溯法的思想,回溯法借助想象出来的树的结构,把问题简单化,使得解问题更方便。通过剪枝函数和约束函数对于求问题的解有很大的帮助,但要把一些限制条件把剪枝函数抽象化。
指导教师对实验报告的评语
成绩:
指导教师签字:
年 月 日
实验六:最小重量机器设计问题(分支限界法)
一、实验时间:20##年11月12日,星期二,第一、二节地点:J13#328
二、实验目的及要求
1、了解分支限界法的基本思想。
2、运用分支限界法解决最小重量机器设计问题。
三、实验环境
平台:win7操作系统
开发工具:codeblocks10.05
四、实验内容
最小重量机器设计问题:设某一机器由n个部件组成,每一种部件可以从m个不同的供应商处购得。设wij是从供应商j处购得的部件i的重量,cij是相应的价格。试设计一个算法,给出总价格不超过c的最小重量机器设计
五、算法描述及实验步骤
算法描述:
解空间为一棵排列树,采用优先队列式分支限界法找出所给的最小重量机器设计,开始时,将排列树的根节点置为当前扩展结点。在初始扩展结点处还设有选定部件是哪个供应商提供的,故cv=0,cw=0,position=0,peer=0,1≤i≤n。x[1:n]记录供应商的选择while完成对排列树内部结点的有序扩展。循环体内依次从活结点优先队列中取出具有最小重量的结点,依次为当前扩展结点。并且花费不超过c并加以扩展,队列为空时则结束循环。当peer=n时,此时扩展结点是叶节点,得到当前的最小重量和最优解数组x。若peer<n时,算法依次产生当前扩展结点的所有儿子节点。对于当前扩展结点的一个儿子结点,计算出当前的重量,当小于当前的最小重量时,将儿子结点插入到活结点优先队列中,而当不下于当前最小重量时,以当前这个结点为根的子树中不可能有比当前最小重量部件选择更好的解,故可将此结点舍去。若在一结点所计算的花费大于所给的最小花费,则剪去以此节点为根的子树。
实验步骤:
1.定义一个优先队列LinkQueue:
void InitQueue(LinkQueue &Q);//创建一个队列-----首尾结点
void DestroyQueue(LinkQueue &Q);//销毁一个队列
void ClearQueue(LinkQueue &Q);//清空队列
int QueueEmpty(LinkQueue &Q);//判断队列是否为空,空则返回TURE,否则返回FLASE
int QueueLength(LinkQueue &Q);//求队列的长度
void EnQueue(LinkQueue &Q,QElemType &e);//拆入e为新的队尾元素
void DeQueue(LinkQueue &Q,QElemType &e);//用e返回队列的对头元素
bool IsEmpty(LinkQueue &Q)//判断队列是否为空
2. 定义类MinWeight,实现函数有:
void Add(int wt,int ct,int i);//往队列插入节点
int FindBest();//实现最小重量机器的查找
void setMW();//函数初始化
void printMW();//打印输出结果
3 实现主函数并完成所有代码。
六、调试过程及实验结果
七、总结
利用分支限界法解决最小重量机器问题,就是构造一个优先队列,按照规定的优先级按最大效益优先的方式查找解空间树,找出满足要求的最优解。通过利用分支限界法解决最小重量机器问题,熟练了对分支限界法的使用。
指导教师对实验报告的评语
成绩:
指导教师签字:
年 月 日
算法设计与分析实验报告班级姓名学号年月日目录实验一二分查找程序实现03页实验二棋盘覆盖问题分治法08页实验三01背包问题的动态规划…
算法设计课程报告课题名称算法设计与实现课题负责人名学号张樱紫0743111317同组成员名单角色无指导教师左劼评阅成绩评阅意见提交…
遗传算法实验报告姓名:**学号:**一、实验目的:熟悉和掌握遗传算法的运行机制和求解的基本方法。遗传算法是一种基于空间搜索的算法,…
1hanoi塔packagesyyimportjavautilpublicclassHanoipublicstaticvoidmo…
算法设计与分析实验报告班级姓名学号20xx年11月18日目录实验一二分查找程序实现01页实验二棋盘覆盖问题04页实验三01背包问题…
算法分析与设计实验报告实验报告题目实验一递归与分治策略一实验目的1加深学生对分治法算法设计方法的基本思想基本步骤基本方法的理解与掌…
算法设计与分析实验报告实验一递归与分治策略应用基础学号姓名班级日期20xx20xx学年第1学期第九周一实验目的1理解递归的概念和分…
算法设计与分析实验报告一实验名称统计数字问题评分实验日期年月日指导教师刘长松姓名刘飞初专业班级计算机0901学号10一实验要求1掌…
算法设计与分析实验报告贪心算法姓名专业班级学号指导教师完成日期XXXXXX3XXXXXXXXX一试验名称贪心算法1写出源程序并编译…