算法设计与分析课程设计.docx
《算法设计与分析课程设计.docx》由会员分享,可在线阅读,更多相关《算法设计与分析课程设计.docx(18页珍藏版)》请在冰豆网上搜索。
算法设计与分析课程设计
成绩评定表
学生姓名
班级学号
专业
信息与计算科学
课程设计题目
矩阵连乘;
批作业处理调度
评
语
组长签字:
成绩
日期
20年月日
课程设计任务书
学院
理学院
专业
信息与计算科学
学生姓名
班级学号
课程设计题目
矩阵连乘;批作业处理调度
实践教学要求与任务:
要求:
1.巩固和加深对基本算法的理解和运用,提高综合运用课程知识进行算法设计与分析的能力。
2.培养学生自学参考书籍,查阅手册、和文献资料的能力。
3.通过实际课程设计,掌握利用分治法或动态规划算法,回溯法或分支限界法等方法的算法的基本思想,并能运用这些方法设计算法并编写程序解决实际问题。
4.了解与课程有关的知识,能正确解释和分析实验结果。
任务:
1.动态规划解决矩阵连乘问题;
2.回溯法解决批作业处理调度问题;
3.总结解决问题的方法与收获。
工作计划与进度安排:
第12周:
查阅资料。
掌握算法设计思想,进行算法设计。
第13周:
算法实现,调试程序并进行结果分析。
撰写课程设计报告,验收与答辩。
指导教师:
201年月日
专业负责人:
201年月日
学院教学副院长:
201年月日
摘要
算法设计与分析,其实可以解释为一类优化问题,一般针对可以利用计算机解决的离散型问题的优化。
主要目的就是为了解决某一问题而提出的各种不同的解决方案。
本文通过计算机算法分析设计出解矩阵连乘的动态规划算法和设计出解批处理作业调度的回溯法算法,利用C++语言编写程序实现算法。
动态规划算法是将待求解的问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。
首先找出最优解的性质,并刻其结构特征,然后递归的定义最优值(写出动态规划方程)并且以自底向上的方式计算出最优值,最后根据计算最优值时得到的信息,构造一个最优解。
回溯法算法是确定了解空间的组织结构后,回溯法就是从开始节点(根结点)出发,以深度优先的方式搜索整个解空间。
这个开始节点就成为一个活结点,同时也成为当前的扩展结点。
在当前的扩展结点处,搜索向纵深方向移至一个新结点。
这个新结点就成为一个新的或节点,并成为当前扩展结点。
如果在当前的扩展结点处不能再向纵深方向移动,则当前的扩展结点就成为死结点。
换句话说,这个节点,这个结点不再是一个活结点。
此时,应往回(回溯)移动至最近一个活结点处,并使这个活结点成为当前的扩展结点。
回溯法即以这种工作方式递归的在解空间中搜索,直到找到所要求的解或解空间中以无活结点为止。
即通过确定初始解和剪枝函数原则画出状态图进行搜索产生全部可行解。
关键词:
动态规划;矩阵连乘;回溯法;批处理作业调度;剪枝原则;C++
目录
一、课程设计目的1
二、课程设计内容1
三、概要设计1
3.1动态规划—矩阵连乘1
3.2回溯法—批处理作业调度2
四、详细设计与实现3
4.1动态规划—矩阵连乘3
4.11问题描述3
4.12分析最优解的结构3
4.13建立递归关系3
4.14计算最优值4
4.15代码实现4
4.16运行结果7
4.2回溯法—批处理作业调度8
4.21问题描述8
4.22算法分析8
4.23代码实现9
4.24运行结果12
总结14
参考文献15
一、课程设计目的
《计算机算法设计与分析》这门课程是一门实践性非常强的课程,要求我们能够将所学的算法应用到实际中,灵活解决实际问题。
通过这次课程设计,能够培养我们独立思考、综合分析与动手的能力,并能加深对课堂所学理论和概念的理解,可以训练我们算法设计的思维和培养算法的分析能力。
二、课程设计内容
1、动态规划:
设计出解矩阵连乘问题的动态规划算法
2、回溯法:
设计出解批处理作业调度的回溯法算法
三、概要设计
3.1动态规划—矩阵连乘
动态规划的基本思想是将问题分解为若干个小问题,解子问题,然后从子问题得到原问题的解。
设计动态规划法的步骤:
(1)找出最优解的性质,并刻画其结构特征;
(2)递归地定义最优值(写出动态规划方程);
(3)以自底向上的方式计算出最优值;
(4)根据计算最优值时得到的信息,构造一个最优解。
3.2回溯法—批处理作业调度
回溯法的基本思想是确定了解空间的组织结构后,回溯法就是从开始节点(根结点)出发,以深度优先的方式搜索整个解空间。
这个开始节点就成为一个活结点,同时也成为当前的扩展结点。
在当前的扩展结点处,搜索向纵深方向移至一个新结点。
这个新结点就成为一个新的或节点,并成为当前扩展结点。
如果在当前的扩展结点处不能再向纵深方向移动,则当前的扩展结点就成为死结点。
换句话说,这个节点,这个结点不再是一个活结点。
此时,应往回(回溯)移动至最近一个活结点处,并使这个活结点成为当前的扩展结点。
回溯法即以这种工作方式递归的在解空间中搜索,直到找到所要求的解或解空间中以无活结点为止。
用回溯法解决批处理作业调度的步骤:
(1)针对所给问题,定义问题的解空间;
(2)确定易于搜索的解空间结构;
(3)以深度优先方式搜索解空间,并在搜索过程中用剪枝函数原则避免无效搜索。
四、详细设计与实现
4.1动态规划—矩阵连乘
4.11问题描述
给定n个矩阵{A1,A2,…,An},其中Ai与Ai+1是可乘的,i=1,2,…,n-1。
如何确定计算矩阵连乘积的计算次序,使得依此次序计算矩阵连乘积需要的数乘次数最少。
例如求n个矩阵A1,A2,A3,A4…….An相乘的最小数乘次数,当A1为10*100的矩阵,A2为100*5的矩阵,A3为5*50的矩阵,则方法((A1A2)A3)的数乘次数为10*100*5+10*5*50=7500,而方法(A1(A2A3))则为100*5*50+10*100*50=75000,两者相差10倍。
4.12分析最优解的结构
设计求解具体问题的动态规划算法的第一步是刻画该问题的最优解的结构特征。
我们将矩阵连乘积AiAi+1....Aj简记为A[i:
j]。
考察计算A[1:
n]的最优计算次序。
设这个计算次序在矩阵Ak和Ak+1之间将矩阵链断开,1<=k以此次序,总的计算量为A[1:
k]的计算量加上A[k+1:
n]的计算量,再加上A[1:
k]和A[k+1:
n]相称的计算量。
这个问题的关键特征是:
计算A[1:
n]的最优次序所包含的计算矩阵子链a[1:
k]和A[k+1:
n]的次序也是最优的。
因此,矩阵连乘积计算次序问题的最优解包含着其子问题的最优解。
这种性质称为最优子结构性质。
问题的最优子结构性质是该问题可以用动态规划算法求解的显著特征。
4.13建立递归关系
设计动态规划算法的第二步就是递归地定义最优值。
对于矩阵连乘积的最有计算次序问题,设计算A[i:
j],1<=i<=j<=n,所需的最少数乘次数为m[i][j],则原问题的最优值为m[1][n]。
当i=j时,A[i ;j]=Ai,为单一矩阵,无需计算,因此m[i][i]=0。
当i事实上,若计算A[i:
j]的最优次序在Ak和Ak+1之间断开,i<=k其中Pi表示第i个矩阵的列数,也是第i-1个矩阵的行数,P0表示第一个矩阵的行数。
由于在计算时并不知道断开点k的位置,所以k还未定。
不过k的位置只有j-i个可能。
从而m[i][j]可以递归地定义为
当i=j m[i][j]=0
当im[i][j]=min{m[i][k]+m[k+1][j]+Pi-1*Pk*Pj}
m[i][j]给出了最优值,即计算A[i:
j]所需的最少数乘次数。
同时还确定了计算A[i:
j]的最优次序中的断开位置k,也就是说,对于这个k有
m[i][j]=m[i][k]+m[k+1][j]+Pi-1*Pk*Pj
若将对应于m[i][j]的断开位置k记为s[i][j],在计算最优值m[i][j]后,可以递归地有s[i][j]构造出相应的最优解。
4.14计算最优值
根据计算m[i][j]的递归式,容易写一个递归算法计算m[1][n]。
但是简单地递归将好费指数计算时间。
在递归计算时,许多子问题被重复计算多次。
这也是该问题可以用动态规划算法求解的又一显著特征。
4.15代码实现
//矩阵连乘
#include
#defineN100
intp[N];//用以记录矩阵的行和列
ints[N][N];//用以记录断开位置
intm[N][N];//用以记录最少数乘次数
intn;//矩阵数目
intkuohao[2][N];//记录加括号的位置
voidinit()
{
inti;
for(i=0;i{
s[i][i]=0;
kuohao[0][i]=0;
kuohao[1][i]=0;
}
}
voidinput()
{
inti;
printf("pleaseputinthenumofmatrix:
\n");
scanf("%d",&n);
printf("pleaseputinthematrixs:
\n");
for(i=0;i<=n;++i)
scanf("%d",&p[i]);
}
voidmatrix()
{
inti,j,k,t;
intd;
for(d=1;dfor(i=1;i<=n-d;++i)
{
j=i+d;
m[i][j]=m[i+1][j]+p[i-1]*p[i]*p[j];
s[i][j]=i;
for(k=i+1;k{
t=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];
if(t{
m[i][j]=t;
s[i][j]=k;
}
}
}
}
voidoutput()
{
printf("theleasttimesofmatrixis:
");
printf("%d\n",m[1][n]);
printf("thewayofitis:
\n");
}
voidtranceback(inti,intj)
{
if(i==j)
return;
tranceback(i,s[i][j]);
tranceback(s[i][j]+1,j);
kuohao[0][i]++;
kuohao[1][j]++;
kuohao[1][s[i][j]]++;
kuohao[0][s[i][j]+1]++;
}
voidtrance()
{
inti,j;
for(i=1;i<=n;++i)
{
for(j=1;jprintf("(");
printf("A%d",i);
for(j=1;jprintf(")");
}
printf("\n");
}
intmain()
{
init();
input();
matrix();
output();
tranceback(1,n);
trance();
return0;
}
4.16运行结果
4.2回溯法—批处理作业调度
4.21问题描述
给定n个作业,集合J=(J1,J2,J3)。
每一个作业Ji都有两项任务分别在2台机器上完成。
每个作业必须先有机器1处理,然后再由机器2处理。
作业Ji需要机器j的处理时间为tji。
对于一个确定的作业调度,设Fji是作业i在机器j上完成处理时间。
则所有作业在机器2上完成处理时间和f=F2i,称为该作业调度的完成时间和。
对于给定的n个作业,指定最佳作业调度方案,使其完成时间和达到最小。
4.22算法分析
从n个作业中找出有最小完成时间和的作业调度,所以批处理作业调度问题的解空间是一棵排列树。
类Flowshop的数据成员记录解空间的结点信息,M输入作业时间,bestf记录当前最小完成时间和,bestx记录相应的当前最佳作业调度。
在递归函数Backtrack中,
当i>n时,算法搜索至叶子结点,得到一个新的作业调度方案。
此时算法适时更新当前最优值和相应的当前最佳调度。
当i
4.23代码实现
#include
usingnamespacestd;
#defineMAX200
int*x1;//作业Ji在机器1上的工作时间;
int*x2;//作业Ji在机器2上的工作时间;
intnumber=0;//作业的数目;
int*xOrder;//作业顺序;
int*bestOrder;//最优的作业顺序;
intbestValue=MAX;//最优的时间;
intxValue=0;//当前完成用的时间;
intf1=0;//机器1完成的处理时间;
int*f2;//第i阶段机器2完成的时间;
voidBackTrace(intk)
{
if(k>number)
{
for(inti=1;i<=number;i++)
{
bestOrder[i]=xOrder[i];
}
bestValue=xValue;
}
else
{
for(inti=k;i<=number;i++)
{
f1+=x1[xOrder[i]];
f2[k]=(f2[k-1]>f1?
f2[k-1]:
f1)+x2[xOrder[i]];
xValue+=f2[k];
swap(xOrder[i],xOrder[k]);
if(xValue{
BackTrace(k+1);
}
swap(xOrder[i],xOrder[k]);
xValue-=f2[k];
f1-=x1[xOrder[i]];
}
}
}
intmain()
{
cout<<"请输入作业数目:
";
cin>>number;
x1=newint[number+1];
x2=newint[number+1];
xOrder=newint[number+1];
bestOrder=newint[number+1];
f2=newint[number+1];
x1[0]=0;
x2[0]=0;
xOrder[0]=0;
bestOrder[0]=0;
f2[0]=0;
cout<<"请输入每个作业在机器1上所用的时间:
"<for(inti=1;i<=number;i++)
{
cout<<"第"<
cin>>x1[i];
}
cout<<"请输入每个作业在机器2上所用的时间:
"<for(i=1;i<=number;i++)
{
cout<<"第"<
cin>>x2[i];
}
for(i=1;i<=number;i++)
{
xOrder[i]=i;
}
BackTrace
(1);
cout<<"最节省的时间为:
"<cout<cout<<"对应的方案为:
";
for(i=1;i<=number;i++)
{
cout<}
return0;
}
4.24运行结果
总结
通过本次课程设计,使我对矩阵连乘、批处理作业调度设计的基本过程的设计方法、步骤、思路、有了一定的了解与认识。
在这次课程设计过程中,我认识到只是知道课本上的理论知识是远远不够的,我们还必须要深切的理解每个算法的思想,并且能够利用C++语言去编写相关的代码,经过不断的修改、调试,使之能解决相应的问题,最终能运用到实际案例中去。
对我们来说,实际能力的培养至关重要,而这种实际能力的培养单靠课堂教学是远远不够的,必须从课堂走向实践。
而这次的课程设计,正好给了我们一个机会让我们找出自身状况与实际需要的差距,并在以后的学习期间及时补充相关知识,为求职与正式工作做好充分的知识、能力准备,从而缩短从校园走向社会的心理转型期。
参考文献
[1]王晓东.计算机算法设计与分析(第4版).北京.电子工业出版社.2012.2
[2]王晓云、陈业纲.计算机算法设计、分析与实现.北京.科学出版社.2012
[3]谭浩强.C语言程序设计(第3版).北京.清华大学出版社.2012
[4]陈玉福.算法设计与分析.北京.清华大学出版社.2009
[5]严蔚敏.数据结构.北京.清华大学出版社.2009