算法实验3最大子段和问题实验报告.docx
- 文档编号:5502577
- 上传时间:2022-12-17
- 格式:DOCX
- 页数:13
- 大小:92.75KB
算法实验3最大子段和问题实验报告.docx
《算法实验3最大子段和问题实验报告.docx》由会员分享,可在线阅读,更多相关《算法实验3最大子段和问题实验报告.docx(13页珍藏版)》请在冰豆网上搜索。
算法实验3最大子段和问题实验报告
昆明理工大学信息工程与自动化学院学生实验报告
(2011—2012学年第1学期)
课程名称:
算法设计与分析开课实验室:
信自楼机房4442012年12月14日
年级、专业、班
学号
姓名
成绩
实验项目名称
最大子段和问题
指导教师
吴晟
教师评语
该同学是否了解实验原理:
A.了解□B.基本了解□C.不了解□
该同学的实验能力:
A.强□B.中等□C.差□
该同学的实验是否达到要求:
A.达到□B.基本达到□C.未达到□
实验报告是否规范:
A.规范□B.基本规范□C.不规范□
实验过程是否详细记录:
A.详细□B.一般□C.没有□
教师签名:
年月日
一、上机目的及内容
1.上机内容
给定有n个整数(可能有负整数)组成的序列(a1,a2,…,an),求改序列形如
的子段和的最大值,当所有整数均为负整数时,其最大子段和为0。
2.上机目的
(1)复习数据结构课程的相关知识,实现课程间的平滑过渡;
(2)掌握并应用算法的数学分析和后验分析方法;
(3)理解这样一个观点:
不同的算法能够解决相同的问题,这些算法的解题思路不同,复杂程度不同,解题效率也不同。
二、实验原理及基本技术路线图(方框原理图或程序流程图)
(1)分别用蛮力法、分治法和动态规划法设计最大子段和问题的算法;
蛮力法设计原理:
利用3个for的嵌套(实现从第1个数开始计算子段长度为1,2,3…n的子段和,同理计算出第2个数开始的长度为1,2,3…n-1的子段和,依次类推到第n个数开始计算的长为1的子段和)和一个if(用来比较大小),将其所有子段的和计算出来并将最大子段和赋值给summax1。
用了3个for嵌套所以时间复杂性为○(n3);
分治法设计原理:
1)、划分:
按照平衡子问题的原则,将序列(
,
,…,
)划分成长度相同的两个字序列(
,…,
)和(
,…,
)。
2)、求解子问题:
对于划分阶段的情况分别的两段可用递归求解,如果最大子段和在两端之间需要分别计算s1=
,s2=
,则s1+s2为最大子段和。
若然只在左边或右边,那就好办了,前者视s1为summax2,后者视s2osummax2。
3)、合并:
比较在划分阶段的3种情况下的最大子段和,取三者之中的较大者为原问题的解。
4)、时间复杂性分析:
f(n)=2*f(n/2)+○(n/2),最后为○(nlogn)。
动态规划法设计原理:
动态规划法求解最大字段和问题的关键是要确定动态规划函数。
记
则
由b(j)的定义,当b(j-1)>0是,b(j)=b(j-1)+a,否则,b(j)=a。
可得如下递推式:
代码实现过程中只用了一个for,时间复杂性为:
○(n)
(2)对所设计的算法采用大O符号进行时间复杂性分析;
蛮力法时间复杂性为○(n3);
分治法时间复杂性为○(nlogn)
动态规划法时间复杂性为:
○(n)
(3)上机实现算法,并用计数法和计时法分别测算算法的运行时间;
详情见运行结果。
(4)通过分析对比,得出自己的结论。
结论:
蛮力法只可以处理小理的数据。
当数据量超过10000时,由蛮力法要等很久才输出,所以数据量超过10000时,就比较分治法和动态规划法。
由实验结果可知,动态规划法所用的时间要少。
实验原理图:
三、所用仪器、材料(设备名称、型号、规格等或使用软件)
1台PC及VISUALC++6.0软件。
绘制流程图软件:
DiagramDesigner.
四、实验方法、步骤(或:
程序代码或操作过程)
部分重要代码说明:
#include
#include
intgetMaxSum1(intiarray[],intn)/*蛮力法函数*/
intgetMaxSum2(intiarray[],intstartIndex,intendIndex)//分治法函数
intgetMaxSum3(intiarray[],intn)/*动态规划方法函数*/
intOUT_PRINTF()//输出最大字段求解的函数
intmain()//主函数
#include
#include
#include
usingnamespacestd;
/*蛮力法*/
intgetMaxSum1(intiarray[],intn)
{
intmaxSum=0;//初始化maxSum
for(inti=0;i { for(intj=i;j { inttmp=0;//初始化tmp(子段和) for(intk=i;k<=j;++k) { tmp+=iarray[k]; } if(tmp>maxSum)//比较子段和,得出最大的子段和maxSum { maxSum=tmp; } } } returnmaxSum; } 源程序代码: /*分治递归方法*/ intgetMaxSum2(intiarray[],intstartIndex,intendIndex) { if(endIndex==startIndex)//只有一个元素 { returniarray[startIndex]; } if(endIndex-startIndex==1)//两个元素时 { inttmp=iarray[startIndex]+iarray[endIndex]; tmp=tmp>iarray[startIndex]? tmp: iarray[startIndex]; tmp=tmp>iarray[endIndex]? tmp: iarray[endIndex]; returntmp; } //左边一半序列的最大子段和leftMaxSum intleftMaxSum=getMaxSum2(iarray,startIndex,(startIndex+endIndex)/2); //右边一半序列的最大子段和rightMaxSum intrightMaxSum=getMaxSum2(iarray,(startIndex+endIndex)/2+1,endIndex); ints1=0; ints2=0; inttmp=0; for(inti=(startIndex+endIndex)/2;i>=startIndex;--i)//左子段和 { tmp=tmp+iarray[i]; if(tmp>s1) { s1=tmp; } } tmp=0; for(i=(startIndex+endIndex)/2+1;i<=endIndex;++i)//右子段和 { tmp=tmp+iarray[i]; if(tmp>s2) { s2=tmp; } } intmiddleMaxSum=s1+s2; intmaxSum=leftMaxSum>rightMaxSum? leftMaxSum: rightMaxSum; maxSum=maxSum>middleMaxSum? maxSum: middleMaxSum; returnmaxSum; } /*动态规划方法*/ intgetMaxSum3(intiarray[],intn) { intmaxSum=0; intb=0; for(inti=0;i { if(b>0) { b=b+iarray[i]; } else { b=iarray[i]; } if(b>maxSum) { maxSum=b;} } returnmaxSum; } intOUT_PRINTF()//输出最大字段求解的函数 { intn,i,cho; clock_tt1,t2,t3,t4,t5,t6; cout<<"****************************************\n"; cout<<"**求最大字段和问题**\n"; cout<<"****************************************\n"; cout< cout<<"/*********手动输入,请按1,随机输入请按2*********/\n"; cin>>cho; cout<<"请输入序列的长度"< cin>>n; int*iarray=newint[n]; if(cho==2) { srand((unsigned)time(NULL)); //cout<<"随机序列为: "< for(i=1;i<=n;i++) { iarray[i]=(rand()/13-1129); //cout<<""< } } else { cout<<"请输入序列"< for(i=0;i cin>>iarray[i]; } t1=clock();//使用蛮力法求解的开始时间 intmaxSum1=getMaxSum1(iarray,n); t2=clock();//蛮力法求解的结束时间 cout< cout<<"--------------------------------------------------\n"; cout<<"蛮力法最大子段和为: "< cout<<"时间: "< t3=clock();//分治法求解的开始时间 intmaxSum2=getMaxSum2(iarray,0,n-1); t4=clock();//分治法求解的结束时间 cout<<"--------------------------------------------------\n"; cout<<"分治法最大子段和为: "< cout<<"时间: "< t5=clock();//动态规划法求解的开始时间 intmaxSum3=getMaxSum3(iarray,n); t6=clock();//动态规划法求解的结束时间 cout<<"--------------------------------------------------\n"; cout<<"动态规划法最大子段和为: "< cout<<"时间: "< return0; } intmain()//主函数 { inti; chara,y,Y,b; OUT_PRINTF();//调用输出函数 for(i=1;i<10;i++) { cout<<"是否继续输入? Y/N"< cin>>a; if(a=='y'||a=='Y') { OUT_PRINTF(); } if(a=='n'||a=='N') { return0; } } return0; } 五、实验过程原始记录(测试数据、图表、计算等) 测试程序: 输入选择的方式求最大子段和问题。 手动输入适合序列长度短的时候: 当要测试序列长度很大的时候,经过测试,蛮力法的输出时间太长,所以先省去蛮力法的测试。 当序列长度很大是,只调用动态规划法和分治法。 结果如下: 经过测试可知,动态规划法是最佳的选择。 六、实验结果、分析和结论(误差分析与数据处理、成果总结等。 其中,绘制曲线图时必须用计算纸或程序运行结果、改进、收获) 此次实验主要是设计了三种方法来求解最大子段和问题。 在此次实验中遇到过很多问题,如设置循环时,条件不合理,导致没有出来理想中得结果。 还有,为了得出每种方法求解的时间,添加了一个时间函数的头文件,程序中用到了clock()函数,clock()函数计算出来的是硬件滴答的数目,不是毫秒。 在TC2.0中硬件每18.2个滴答是一秒,在VC++6.0中硬件每1000个滴答是一秒。 C/C++中的计时函数是clock(),而与其相关的数据类型是clock_t。 故计算时间的公式为float(ti-ti-1)/CLK_TCK,其中clock_t是用来保存时间的数据类型,在time.h文件中,我们可以找到对它的定义。 用计算机解决复杂的问题,往往把一个大的、复杂的问题根据其功能划分为不同的模块,每一个模块完成一独立的功能.如果每一个模块用计算机语言来实现,那么当所有模块都实现时,即为对复杂问题的解决.最大子段和问题就是一具有独立功能的小模块,在很多大的问题中都涉及到此问题,用不同的算法解决此问题,并分析其优劣。 注: 教师必须按照上述各项内容严格要求,认真批改和评定学生成绩。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 算法 实验 最大 问题 报告
![提示](https://static.bdocx.com/images/bang_tan.gif)