算法实验报告.docx

上传人:b****6 文档编号:5061179 上传时间:2022-12-12 格式:DOCX 页数:17 大小:94.20KB
下载 相关 举报
算法实验报告.docx_第1页
第1页 / 共17页
算法实验报告.docx_第2页
第2页 / 共17页
算法实验报告.docx_第3页
第3页 / 共17页
算法实验报告.docx_第4页
第4页 / 共17页
算法实验报告.docx_第5页
第5页 / 共17页
点击查看更多>>
下载资源
资源描述

算法实验报告.docx

《算法实验报告.docx》由会员分享,可在线阅读,更多相关《算法实验报告.docx(17页珍藏版)》请在冰豆网上搜索。

算法实验报告.docx

算法实验报告

实验名称:

分治法合并排序

实验时间:

2017.3.24

实验目的和要求:

1.掌握合并排序的基本思想

2.掌握合并排序的实现方法

3.学会分析算法的时间复杂度

4.学会用分治法解决实际问题

实验内容和原理:

随机产生一个整型数组,然后用合并排序将该数组做升序排列,要求输出排序前和排序后的数组。

主要仪器设备:

名称:

Inspiron157000系列(游匣7000)(湛黑)

编译器:

VisualStudioCommunity2015

系统:

win8.0

上机调试修改源程序:

#include"stdafx.h"

#include"iostream"

usingnamespacestd;

voidMerge(int*l,int*temp,intleft,intmid,intright)

{intk=0;

inti=left,j=mid+1;//避免重复比较l[mid]

mid=(left+right)/2;

while((i<=mid)&&(j<=right))

//数组l(mid,right]与数组l(mid,right]均没有全部归入数组temp中去

{if(l[i]<=l[j])//将较小的数放入中间数组

{temp[k++]=l[i++];}

else

{temp[k++]=l[j++];}

}

while(i<=mid)

//表示数组l(mid,right]已经全部归入temp数组中去了,而数组l[left,right]还有剩余

{//将数组l[left,right]剩下的值,逐一归入数组temp

temp[k++]=l[i++];

}

while(j<=right)

{temp[k++]=l[j++];}

for(i=0;i

l[left+i]=temp[i];

}

voidMergesort(int*l,int*temp,intleft,intright)//分化函数并调用合并函数

{if(left

intmid=(left+right)/2;

Mergesort(l,temp,left,mid);//左边有序

Mergesort(l,temp,mid+1,right);//右边有序

Merge(l,temp,left,mid,right);//再将两个有序序列合并

}

}

intmain()

{intLength;

cout<<"输入产生数组的个数:

";

cin>>Length;

int*l=newint[Length];//新建数组

cout<<"产生的随机数组为:

"<

for(inti=0;i

{

l[i]=(rand()%(100-0+1))+0;//调用随机函数产生0-100的随机数

cout<

};

if(inti=Length){cout<

int*p=newint[Length];

Mergesort(l,p,0,Length-1);

cout<<"排序后的数组为:

"<

for(intt=0;t

{cout<

cout<

delete[]p;

return0;

}

实验结果与分析

 

分析:

二路合并排序是分治算法。

它将一个序列分解成两个长度几乎相等的子序列,对它们分别排序,然后调用merge函数合并成一个有序子序列。

基本运算是元素比较,时间复杂度O(nlogn)。

使用与原序列相同长度的辅助数组temp,所需额外空间O(n)

讨论,心得(可选):

能够掌握分治法的步骤,划分,求解子问题,合并。

对分治问题有了更深的体会。

它是将原问题划分为彼此相互独立,规模较小可求解的子问题。

 

实验名称:

贪心法作业调度

实验时间:

2017.3.31

实验目的和要求:

1.掌握贪心算法的基本思想

2.掌握贪心算法的典型问题求解

3.进一步多机调度的基本思想和算法设计方法

4.学会用贪心法分析和解决实际问题

实验内容和原理:

设计贪心算法实现作业调度,要求按作业调度顺序输出作业序列。

如已知要处理的作业数n=8,作业完成的期限为 d=(4, 2, 4, 5, 6, 4, 5, 7),其效益值自行给定,求该条件下的最大效益。

主要仪器设备:

名称:

Inspiron157000系列(游匣7000)(湛黑)

编译器:

VisualStudioCommunity2015

系统:

win8.0

上机调试修改源程序:

#include"stdafx.h"

#include"iostream"

#definen8

usingnamespacestd;

voiddisplay(int*x,int*p,int*d)//输出函数

{intt;

for(t=0;t

{if((t+1)%4==0)//每行4组

cout<<"【"<

else{cout<<"【"<

}

}

intmain()

{intd[n]={4,2,4,5,6,4,5,7};//时限

intp[n]={1,3,5,7,2,4,6,8};//效益值

intx[n]={0,1,2,3,4,5,6,7};//序号

inttime[n]={-1,-1,-1,-1,-1,-1,-1,-1};

inti,j;//虚时间片初始都空

cout<<"初始数据【序号】(效益值,时限):

"<

display(x,p,d);

/*效益值非递增排序函数*/

intt1,t2;

for(i=0;i

for(j=0;j

{if(p[j+1]>p[j])

{t1=p[j+1];p[j+1]=p[j];p[j]=t1;//效益值新排序

t2=x[j+1];x[j+1]=x[j];x[j]=t2;//序号新排序

}

}

cout<<"排序后数据【序号】(效益值,时限):

"<

display(x,p,d);

/*FJS(引入虚时间片数组time)*/

cout<<"作业可行解是:

X=(";

intW=0;//初始效益值是0

for(i=0;i

{intday=d[x[i]];//每个作业都放在可最晚执行的虚时间片内

for(j=day-1;j>=0;j--)//若非空则向前寻找

if(time[j]==-1)

{W+=p[i];//求最大效益值

time[j]=x[i];//标记时间片非空

cout<

break;

}//一旦找到满足的位置就输出并退出循环

}//找不到就不输出

cout<<")"<

cout<<"作业的调度顺序是:

X=(";

for(i=0;i

if(time[i]!

=-1)cout<

cout<<")"<

cout<<"效益值最大是:

"<

return0;

}

实验结果与分析

 

分析:

带时限的作业排序是一种贪心算法。

并选择使用了FJS,引入了虚时间片的概念,并优化了判定方法,假设已经按收益非递增次序排列,为收益最大的作业0分配时间片[d0-1,d0],为收益次大的作业1分配时间片[d1-1,d1],如果该时间片已经分配,再考虑前一个时间片,依次向前寻找第一个空闲时间片,分配之。

如果d1之前的时间片均已经分配,则作业1应该舍弃。

算法时间最坏复杂度由O(n^2)减少到接近O(n)。

 

讨论、心得(可选):

对贪心法的应用求解有了很大的提高,贪心法是求解组合优化的一种设计技术,求解过程是一系列的决策构成,关键是最优子结构和贪心策略。

实验名称:

动态规划法求多段图问题

实验时间:

2017.4.21

实验目的和要求:

1.掌握动态规划算法的基本思想

2.掌握多段图的动态规划算法

3.选择邻接表或邻接矩阵方式来存储图

4.分析算法求解的复杂度。

实验内容和原理:

设G=(V,E)是一个带权有向图,其顶点的集合V被划分成k>2个不相交的子集Vi,1

图中所有边的始点和终点都在相邻的两个子集Vi和Vi+1中。

求一条s到t的最短路线。

参考讲义p136图5-24中的多段图,试选择使用向前递推算法或向后递推算法求解多段图问题。

主要仪器设备:

名称:

Inspiron157000系列(游匣7000)(湛黑)

编译器:

VisualStudioCommunity2015

系统:

win8.0

上机调试修改源程序:

#include"stdafx.h"

#include"limits.h"

#include"iostream"

usingnamespacestd;

voidInit_Graph(intN,intk,int**S,int**C)

{

intX;

inti,j;

inttemp=N;

cout<<"输入边的长度:

输入124表示点1与2的边的长度为4:

首数字为0表示结束输入"<

cin>>i;

while(i!

=0)

{

cin>>j;

cin>>C[i][j];

cin>>i;

}

cout<<"输入每个阶段有哪些点:

输入:

X123表示该阶段有X个点,分别为1,2,3:

"<

for(i=1;i<=k;i++)

{

cout<<"输入第"<

";

cin>>X;

cout<<"这些点分别为:

";

for(j=0;j

{

cin>>S[i][j];

}

}

}

voidPlan(intN,intk,int**S,int**F,int**C,int*result)

{

inti,j,t=N;

intm;

intpoint;

//cout<

point=S[k][0];

for(i=k-1;i>=1;i--)//阶段

{

j=0;//i阶段的状态

while(S[i][j]!

=0)//状态

{

m=0;//i+1阶段的状态

F[i][j]=INT_MAX;

if(C[S[i][j]][point]==INT_MAX)

{

while(S[i+1][m]!

=0)

{

if(C[S[i][j]][S[i+1][m]]!

=INT_MAX)

{

if(F[i][j]>(F[i+1][m]+C[S[i][j]][S[i+1][m]]))

{

F[i][j]=F[i+1][m]+C[S[i][j]][S[i+1][m]];

result[S[i][j]]=S[i+1][m];

t--;

}

}

m++;

}

}

else

{

while(S[i+1][m]!

=0)

{

if(F[i][j]>(F[i+1][m]+C[S[i][j]][S[i+1][m]]))

{

F[i][j]=F[i+1][m]+C[S[i][j]][S[i+1][m]];

result[S[i][j]]=S[i+1][m];

t--;

}

m++;

}

}

j++;

}

}

cout<<"符合条件的点为:

"<

t=0;

result[t]=1;

cout<

t=result[t];

while(t

{

cout<

t=result[t];

}

cout<

";

cout<

}

intmain(intargc,char*argv[])

{

intN,k;

inti,j;

int**C,**S,**F;//C:

边的长度,S;每个阶段的状态;F:

记录每个阶段的状态中的点到终点的距离

int*result;//输出点

cout<<"输入点的个数:

";

cin>>N;

cout<<"输入阶段数:

";

cin>>k;

C=newint*[N+1];

//C=(int**)malloc(sizeof(int*)*(N+1));

for(i=0;i

{

//C[i]=(int*)malloc(sizeof(int)*(N+1));

C[i]=newint[N+1];

for(j=0;j

{

C[i][j]=INT_MAX;

}

}

S=newint*[N+1];

for(i=0;i

{

S[i]=newint[N+1];

memset(S[i],0,sizeof(int)*(N+1));

}

F=newint*[N+1];

for(i=0;i

{

F[i]=newint[N+1];

for(j=0;j

{

F[i][j]=0;

}

}

result=newint[N+1];

memset(result,0,sizeof(int)*(k+1));

Init_Graph(N,k,S,C);

/*

多段图的动态规划方法

阶段:

k

状态:

Sk:

即每个阶段可供选择的点的位置

决策:

u

规划方程:

f(k)=min(f(k+1)+边u的长度。

f(k)表示:

k点到终点的最短路径长度

初始值:

F(k)=0;

*/

Plan(N,k,S,F,C,result);

delete[]result;

for(i=0;i

{

delete[]C[i];

}

delete[]C;

for(i=0;i

{

delete[]S[i];

}

delete[]S;

for(i=0;i

{

delete[]F[i];

}

delete[]F;

return0;

}

实验结果与分析

分析:

算法所用空间除邻接矩阵和最优解path以外,还需要长度为n的cost和d两个局部做为数组。

并不使用二维数组cost[i,j],而是使用一维数组cost[j]保存j到t的最短路径长度,可以节省空间。

对图G的结点按阶段顺序从0到n-1编号,向前递推按结点编号从大到小次序进行,先计算cost[n-1]=0,再计算cost[n-2],cost[0]中保存最短路径长度。

另建一维数组p保存cost[0]最短路径上结点,它是问题最优解。

这一算法时间分析和DFS,BFS相似,时间复杂度是O(n)。

讨论、心得(可选):

动态规划法将原问题归约为规模较小,结构相同的子问题,建立原问题与子问题优化函数间的依赖关系,从规模较小的子问题开始,利用依赖关系求解规模更大的子问题,直到得到原始问题的解为止,采用逐步向前递推的方式,由子问题最优解来计算原问题最优解。

实验名称:

回溯法求N皇后问题

实验时间:

2017.4.28

实验目的和要求:

1.掌握回溯算法的基本思想

2.通过n皇后问题求解熟悉回溯法

3.使用蒙特卡洛方法分析算法的复杂度

实验内容和原理:

要求在一个8*8的棋盘上放置8个皇后,使得它们彼此不受“攻击”。

两个皇后位于棋盘上的同一行、同一列或同一对角线上,则称它们在互相攻击。

现在要找出使得棋盘上8个皇后互不攻击的布局。

主要仪器设备:

名称:

Inspiron157000系列(游匣7000)(湛黑)

编译器:

VisualStudioCommunity2015

系统:

win8.0

上机调试修改源程序:

#include"stdafx.h"

#include"iostream"

usingnamespacestd;

intnum=0;

boolplace(intk,inti,int*x)//判定两个皇后是否在同一列或同一直线

{for(intt=0;t

if((x[t]==i)||(abs(x[t]-i)==abs(t-k)))returnfalse;

returntrue;//不在同一列或同一直线true

}

voidnq(intk,intn,int*x)

{inti;

for(i=0;i

{if(place(k,i,x))//约束函数

{x[k]=i;

if(k==n-1)

{num++;

cout<<"第"<

"<

cout<<"X=(";//输出一个可行解向量

for(i=0;i

cout<<")"/*<

if(num%3==0)cout<

for(i=0;i

{for(intp=0;p

{if(p==x[i])cout<<"Q"<<"";

elsecout<<"*"<<"";

}

cout<

}

}

elsenq(k+1,n,x);//深度优先进入下一层

}

}

}

intmain()

{intn=8;

intx[8];

cout<<"n-皇后算法的解为:

"<

nq(0,n,x);

return0;

}

实验结果与分析

向量X

布局图(部分)

分析:

n皇后问题采用回溯法,以检查两个皇后是否冲突作为基本运算,先令x0=0,再从x1=0开始检测,如果与其他皇后发生冲突,x1再继续相加,x1=2成立。

再令x2=0。

如果x2=0,1,2,3都不行,就回溯到x1,依次进行此操作。

该算法最坏情形O(3n*2n)=O(n^(n+1))。

n皇后问题有n!

个叶结点,遍历时间为O(n!

讨论、心得(可选):

在算法设计策略中,回溯法是比贪心法和动态规划法更一般的方法。

对n皇后的知识点有了很大了解,编写和调试代码的能力有所提高。

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 高等教育 > 军事

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1