华北电力大学算法实验报告.docx
《华北电力大学算法实验报告.docx》由会员分享,可在线阅读,更多相关《华北电力大学算法实验报告.docx(11页珍藏版)》请在冰豆网上搜索。
![华北电力大学算法实验报告.docx](https://file1.bdocx.com/fileroot1/2023-6/15/b8e6d08d-fe30-4bbb-a678-bf203d161c2d/b8e6d08d-fe30-4bbb-a678-bf203d161c2d1.gif)
华北电力大学算法实验报告
华北电力大学
实验报告
|
实验名称:
算法设计与分析实验
课程名称:
算法设计与程序分析
|
专业班级:
学生:
学号:
2011成绩:
指导教师:
军实验日期:
2013.11
实验一矩阵连乘(动态规划)
一、实验目的:
掌握基本的动态规划思想,学习解决格路问题的基本思想。
二、实验容:
给定n个矩阵{A1,A2,…,An},其中Ai与Ai+1是可乘的,i=1,2,…,n-1。
要算出这n个矩阵的连乘积A1A2…An。
由于矩阵乘法满足结合律,故计算矩阵的连乘积可以有许多不同的计算次序。
这种计算次序可以用加括号的方式来确定。
若一个矩阵连乘积的计算次序完全确定,也就是说该连乘积已完全加括号,则可以依此次序反复调用2个矩阵相乘的标准算法计算出矩阵连乘积。
完全加括号的矩阵连乘积可递归地定义为:
(1)单个矩阵是完全加括号的;
(2)矩阵连乘积A是完全加括号的,则A可表示为2个完全加括号的矩阵连乘积B和C的乘积并加括号,即A=(BC)。
例如,矩阵连乘积A1A2A3A4有5种不同的完全加括号的方式:
(A1(A2(A3A4))),(A1((A2A3)A4)),((A1A2)(A3A4)),((A1(A2A3))A4),(((A1A2)A3)A4)。
每一种完全加括号的方式对应于一个矩阵连乘积的计算次序,这决定着作乘积所需要的计算量。
若A是一个p×q矩阵,B是一个q×r矩阵,则计算其乘积C=AB的标准算法中,需要进行pqr次数乘。
为了说明在计算矩阵连乘积时,加括号方式对整个计算量的影响,先考察3个矩阵{A1,A2,A3}连乘的情况。
设这三个矩阵的维数分别为10×100,100×5,5×50。
加括号的方式只有两种:
((A1A2)A3),(A1(A2A3)),第一种方式需要的数乘次数为10×100×5+10×5×50=7500,第二种方式需要的数乘次数为100×5×50+10×100×50=75000。
第二种加括号方式的计算量时第一种方式计算量的10倍。
由此可见,在计算矩阵连乘积时,加括号方式,即计算次序对计算量有很大的影响。
于是,自然提出矩阵连乘积的最优计算次序问题,即对于给定的相继n个矩阵{A1,A2,…,An}(其中矩阵Ai的维数为pi-1×pi,i=1,2,…,n),如何确定计算矩阵连乘积A1A2…An的计算次序(完全加括号方式),使得依此次序计算矩阵连乘积需要的数乘次数最少。
穷举搜索法的计算量太大,它不是一个有效的算法,本实验采用动态规划算法解矩阵连乘积的最优计算次序问题。
三、基本思想
动态规划算法的基本思想是将待求解问题分成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。
与分治法不同的是,动态规划法经分解得到的子问题往往不是相互独立的,前一子问题的解为后一子问题的解提供有用的信息,可以用一个表来记录所有已解决的子问题的答案,不管该子问题以后是否被用到,只要它被计算过,就将其结果填入表中。
本实验的算法思路是:
1、计算最优值算法MatrixChain():
建立两表(即程序中的**m和**s,利用二维指针存放),一表存储矩阵相乘的最小运算量,主对角线上的值为0,依次求2个矩阵、3个矩阵…、直到n个矩阵相乘的最小运算量,其中每次矩阵相乘的最小运算量都在上一次矩阵相乘的最小运算量的基础上求得,最后一次求得的值即为n个矩阵相乘的最小运算量;另
一表存储最优断开位置。
2、输出矩阵结合方式算法Traceback():
矩阵结合即是给矩阵加括号,打印出矩阵结合方式,由递归过程Traceback()完成。
分三种情况:
(1)只有一个矩阵,则只需打印出A1;
(2)有两个矩阵,则需打印出(A1A2);(3)对于矩阵数目大于2,则应该调用递归过程Traceback()两次,构造出最优加括号方式。
四、实验代码
#include
usingnamespacestd;
constintMAX=100;
//p用来记录矩阵的行列,main函数中有说明
//m[i][j]用来记录第i个矩阵至第j个矩阵的最优解
//s[][]用来记录从哪里断开的才可得到该最优解
intp[MAX+1],m[MAX][MAX],s[MAX][MAX];
intn;//矩阵个数
intmatrixChain()
{
for(inti=0;i<=n;i++)
m[i][i]=0;
for(intr=2;r<=n;r++)//对角线循环
for(inti=0;i<=n-r;i++)//行循环
{
intj=r+i-1;//列的控制
//找m[i][j]的最小值,先初始化一下,令k=i
m[i][j]=m[i+1][j]+p[i+1]*p[i]*p[j+1];
s[i][j]=i;
//k从i+1到j-1循环找m[i][j]的最小值
for(intk=i+1;k{
inttemp=m[i][k]+m[k+1][j]+p[i]*p[k+1]*p[j+1];
if(temp{
m[i][j]=temp;
//s[][]用来记录在子序列i-j段中,在k位置处
//断开能得到最优解
s[i][j]=k;
}
}
}
returnm[0][n-1];
}
//根据s[][]记录的各个子段的最优解,将其输出
voidtraceback(inti,intj)
{
if(i==j)
{
cout<<'A'<
return;
}
if(i
cout<<'(';
traceback(i,s[i][j]);
if(i
cout<<')';
if(s[i][j]+1cout<<'(';
traceback(s[i][j]+1,j);
if(s[i][j]+1cout<<')';
}
voidtraceback(){
cout<<'(';
traceback(0,n-1);
cout<<')';
cout<}
intmain()
{
cout<<"请输入矩阵的个数:
"<cin>>n;
cout<<"输入矩阵(形如a*b,中间用空格隔开):
"<for(inti=0;i<=n;i++)
cin>>p[i];
//测试数据可以设为六个矩阵分别为
//A1[30*35],A2[35*15],A3[15*5],A4[5*10],A5[10*20],A6[20*25]
//则p[0-6]={30,35,15,5,10,20,25}
cout<<"输出结果如下:
"<matrixChain();
traceback(0,n-1);
//最终解值为m[0][n-1];
cout<return0;
}
五、程序截图
实验二n皇后问题(回溯法)
一、实验目的:
掌握回溯算法,并能够编写解决n后问题的程序
二、实验容:
问题:
对任意给定的n求解n后问题。
具体要求:
1、封装n后问题为类,编写以下两种算法进行求解:
1)递归回溯方法;
2)迭代回溯方法。
(选)
2、对任意给定的n,要求输出其解向量(所有解),并输出其解数;
3、构造n后问题的解数表格(由程序自动生成):
n后数
解数
第一个解
4
2
(2,4,1,3)
5
…
…
6
…
…
…
…
…
三、实验思想:
回溯法的基本思想是从问题的某一种状态出发,搜索从这种状态出发所能达到的所有状态,当一条路走到尽头的时候,再后退一步获若干步,从另一种可能的状态出发,继续搜索,直到所有的路径全部试探过为止。
四、实验代码
#ifndef_QUEEN_H_
#define_QUEEN_H_
#include
classQueen
{
private:
intqueens;//totalqueens
int*answer;//answerarray
intsum;//totalanswers
//judgeacertainplaceisavailable,krepresentrow,irepresentcolumn
boolplace(intk,inti)const;
voidprintResult()const;//输出结果
public:
Queen(intn);
~Queen();
voidnqueens(intk=1);
voidprintSum()const{std:
:
cout<:
endl;}
};
#endif
Queen.cpp文件
#include
#include"queen.h"
Queen:
:
Queen(intn)
{
queens=n;
answer=newint[n+1];
sum=0;
}
Queen:
:
~Queen()
{
delete[]answer;
}
voidQueen:
:
nqueens(intk)
{
answer[k]=1;
while(answer[k]<=queens)
{
if(place(k,answer[k]))
{
if(k==queens)
{
sum++;
printResult();
}
else
nqueens(k+1);
}
answer[k]=answer[k]+1;
}
}
boolQueen:
:
place(intk,inti)const
{
intm=1;
while(m{
if(answer[m]==answer[k]||abs(answer[k]-answer[m])==abs(k-m))
returnfalse;
m++;
}
returntrue;
}
voidQueen:
:
printResult()const
{
for(inti=1;i{
std:
:
cout<}
std:
:
cout<:
endl;
}
Mian.cpp文件
#include
#include"queen.h"
usingnamespacestd;
intmain()
{
cout<<"Enterthequeens:
";
intm;
cin>>m;
Queenq=Queen(m);
q.nqueens();
cout<<"Totalmethods:
";
q.printSum();
cout<<"Done!
\n";
return0;
}
五、实验截图
六、实验心得
矩阵连乘问题采用动态规划法解决,通过第一个实验,加深了我对动态规划法的理解。
N皇后问题运用了回溯法,通过使用一些特殊的剪枝函数,达到排列的目的。
通过这次实验设计,我意识到,我们不能仅仅停留在会编程上,当然编程能力必须要进一步加深,此外我们还应掌握优化程序的能力,而且对研究算法设计的重要性有了更加深刻的认知,优化算法的选择对解决实际问题的效率有很大的影响。
选择合适的算法,对于在大规模问题上的处理,效率高的优势就体现出来,在实际问题中能减少很大的工作量。
同时在实验设计的过程中发现了自己的不足之处,对以前所学过的知识理解得不够深刻、掌握得不够牢固,以后应多加巩固,继续学习。
在平时的一些编程问题上多思考也能对旧知识的加深记忆,巩固复习。