算法设计与分析作业三.docx

上传人:b****6 文档编号:8160010 上传时间:2023-01-29 格式:DOCX 页数:9 大小:36.45KB
下载 相关 举报
算法设计与分析作业三.docx_第1页
第1页 / 共9页
算法设计与分析作业三.docx_第2页
第2页 / 共9页
算法设计与分析作业三.docx_第3页
第3页 / 共9页
算法设计与分析作业三.docx_第4页
第4页 / 共9页
算法设计与分析作业三.docx_第5页
第5页 / 共9页
点击查看更多>>
下载资源
资源描述

算法设计与分析作业三.docx

《算法设计与分析作业三.docx》由会员分享,可在线阅读,更多相关《算法设计与分析作业三.docx(9页珍藏版)》请在冰豆网上搜索。

算法设计与分析作业三.docx

算法设计与分析作业三

 

算法设计与分析

实验报告

 

学院信息科学与技术学院

专业班级软件工程3班

学号20122668

姓名王建君

指导教师尹治本

 

2014年10月

 

实验四矩阵相乘次序

1、问题提出

用动态规划算法解矩阵连乘问题。

给定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)为了说明在计算矩阵连乘积时,加括号方式对整个计算量的影响,先考察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的计算次序(完全加括号方式),使得依此次序计算矩阵连乘积需要的数乘次数最少。

2、求解思路

本实验采用动态规划算法解矩阵连乘积的最优计算次序问题。

本实验的算法思路是:

1)计算最优值算法MatrixChain():

建立两张表(即程序中的**m和**s,利用二维指针存放),一张表存储矩阵相乘的最小运算量,主对角线上的值为0,依次求2个矩阵、3个矩阵…、直到n个矩阵相乘的最小运算量,其中每次矩阵相乘的最小运算量都在上一次矩阵相乘的最小运算量的基础上求得,最后一次求得的值即为n个矩阵相乘的最小运算量;另一张表存储最优断开位置。

2)输出矩阵结合方式算法Traceback():

矩阵结合即是给矩阵加括号,打印出矩阵结合方式,由递归过程Traceback()完成。

分三种情况:

(1)只有一个矩阵,则只需打印出A1;

(2)有两个矩阵,则需打印出(A1A2);(3)对于矩阵数目大于2,则应该调用递归过程Traceback()两次,构造出最优加括号方式。

三、算法复杂度

该算法时间复杂度最高为

4、实验源代码

#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]+1

cout<<'(';

traceback(s[i][j]+1,j);

if(s[i][j]+1

cout<<')';

}

voidtraceback()

{

cout<<'(';

traceback(0,n-1);

cout<<')';

cout<

}

intmain()

{

system("title软件3班王建君20122668动态规划求矩阵连乘次序");

cout<<"请输入矩阵的个数:

"<

cin>>n;

cout<<"输入矩阵(形如a*b,中间用空格隔开):

"<

for(inti=0;i<=n;i++)

cin>>p[i];//测试数据可以设为8个矩阵分别为//A1[10*15],A2[15*20],A3[20*5],A4[5*25],A5[25*20],A6[20*5],A7[5*23],A8[23,8]//则p[0-8]={10,15,20,5,25,20,5,23,8}

cout<<"输出结果如下:

"<

matrixChain();

traceback(0,n-1);//最终解值为m[0][n-1];

cout<

return0;

}

5、结果分析

测试数据可以设为8个矩阵分别为/A0[10*15],A1[15*20],A2[20*5],A3[5*25],A4[25*20],A5[20*5],A6[5*23],A7[23,8]则p[0-8]={10,15,20,5,25,20,5,23,8},的最佳相乘次序为(A0(A1A2))(((A3A4)A5)(A6A7))。

 

实验五、找零问题

1、问题提出

设有n种不同面值的硬币,各硬币的面值存于数组t[1:

n]中。

现要用这些面值的硬币来找钱,可以实用的各种面值的硬币个数不限。

当只用硬币面值t[1],t[2],…,t[i]时,可找出钱数M的最少硬币个数记为b[i][j]。

若只用这些硬币面值,找不出钱数M时,记b[i][j]=∞。

2、求解思路

令b[i,j]表示前i(1≤i≤m)种硬币,总额为j(0≤j≤n)的最小硬币数。

目标为求b[m,n]。

由于对第i种硬币,存在可选1个或者不选两种可能,故容易建立递推关系:

b[i,j]=min{b[i-1,j],1+b[i,j-vi]},for1≤i≤m,0≤j≤n

显然,b[i,0]=0,1≤i≤m

如果无解,令b[i,j]=+∞。

特别的,如果i=1,令b[-1,j]=+∞;如果j-vi<0,b[i,j-vi]=+∞

3、算法复杂度

n--钞票面额的个数M--要找的钱数,子问题不重复计算,时间复杂度降低,时间复杂度O(nM)。

4、实验源代码

#include

#include

#defineINFINITY32767//无穷大

#defineMAX100

/*b[i][j]==-1子问题未计算,递归计算

b[i][j]!

=-1子问题已计算,直接取计算结果

另外,也可从b[i][j]算出各种面额的钞票数*/

intDynamicMemory(intt[],inti,intj,intb[][MAX])

{

if(i==1)

{

if(j%t[1]==0)

b[i][j]=j/t[1];

else

b[i][j]=INFINITY;

returnb[i][j];

}

else{

intx;

if(b[i-1][j]==-1)

x=DynamicMemory(t,i-1,j,b);

else

x=b[i-1][j];

if(j

{

b[i][j]=x;

returnx;

}

else

{

inty;

if(b[i][j-t[i]]==-1)

y=DynamicMemory(t,i,j-t[i],b);

else

y=b[i][j-t[i]];

b[i][j]=(x>y+1)?

(y+1):

x;

returnb[i][j];

}

}

}

voidmain()

{

system("title软件3班王建君20122668动态规划实现找零问题");

intt[10],n,M;//n--钞票面额的个数M--要找的钱数

t[0]=0;

printf("请输入钞票面额的种数:

\n");

scanf("%d",&n);

printf("请依次输入%d种钞票的面额:

\n",n);

for(inti=1;i<=n;i++)

scanf("%d",&t[i]);

printf("请输入要找零的钱的总数:

\n");

scanf("%d",&M);

intb[MAX][MAX];

intp[MAX]={0};

for(i=0;i

for(intj=0;j

b[i][j]=-1;

intx=DynamicMemory(t,n,M,b);

if(x==INFINITY)

printf("无解!

\n");

else{

printf("找零钞票总数:

%d\n",x);

intr=M;

intk=n;

while(r>0)

if(r

{

p[k]+=0;

k=k-1;

}

elseif(b[k][r]==b[k][r-t[k]]+1)

{

p[k]+=1;

r=r-t[k];

}

else

{

p[k]+=0;

k=k-1;

}

for(k=n;k>=1;k--)

{

if(p[k]!

=0)

printf("面额为%d的钞票数:

%d\n",t[k],p[k]);

}

}

}

5、结果分析

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

当前位置:首页 > 高等教育 > 工学

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

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