动态规划算法解矩阵连乘问题的源代码知识讲解

合集下载

算法设计与分析——矩阵连乘问题(动态规划)

算法设计与分析——矩阵连乘问题(动态规划)

算法设计与分析——矩阵连乘问题(动态规划)⼀、问题描述引出问题之前我们先来复习⼀下矩阵乘积的标准算法。

int ra,ca;//矩阵A的⾏数和列数int rb,cb;//矩阵B的⾏数和列数void matrixMultiply(){for(int i=0;i<ra;i++){for(int j=0;j<cb;j++){int sun=0;for(int k=0;k<=ca;k++){sum+=a[i][k]*b[k][j];}c[i][j]=sum;}}}给定n个矩阵{A1,A2,…,An},其中Ai与Ai+1是可乘的,i=1,2…,n-1。

如何确定计算矩阵连乘积的计算次序,使得依此次序计算矩阵连乘积需要的数乘次数最少。

例如,给定三个连乘矩阵{A1,A2,A3}的维数分别是10*100,100*5和5*50,采⽤(A1A2)A3,乘法次数为10*100*5+10*5*50=7500次,⽽采⽤A1(A2A3),乘法次数为100*5*50+10*100*50=75000次乘法,显然,最好的次序是(A1A2)A3,乘法次数为7500次。

加括号的⽅式对计算量有很⼤的影响,于是⾃然地提出矩阵连乘的最优计算次序问题,即对于给定的相继n个矩阵,如何确定矩阵连乘的计算次序,使得依此次序计算矩阵连乘积需要的数乘次数最少。

⼆、问题分析矩阵连乘也是Catalan数的⼀个常⽤的例⼦,关于时间复杂度的推算需要参考离散数学关于Catalan的内容。

下⾯考虑使⽤动态规划法解矩阵连乘积的最优计算次序问题。

1、分析最优解的结构问题的最优⼦结构性质是该问题可以⽤动态规划求解的显著特征!!!2、建⽴递归关系3、计算最优值public static void matrixChain(int n) {for (int i = 1; i <= n; i++) {m[i][i] = 0;}for (int r = 2; r <= n; r++) {//i与j的差值for (int i = 1; i <= n - r + 1; i++) {int j = i + r - 1;m[i][j] = m[i + 1][j] + p[i - 1] * p[i] * p[j];s[i][j] = i;for (int k = i + 1; k < j; k++) {int t = m[i][k] + m[k + 1][j] + p[i - 1] * p[k] * p[j];if (t < m[i][j]) {m[i][j] = t;s[i][j] = k;}}}}}4、构造最优解public static void traceback(int i, int j) {if (i == j) {System.out.printf("A%d", i); // 输出是第⼏个数据return;}System.out.printf("(");traceback(i, s[i][j]);// 递归下⼀个数据System.out.printf(" x ");traceback(s[i][j] + 1, j);System.out.printf(")");}三、总结。

矩阵连乘的动态规划

矩阵连乘的动态规划

给定n个矩阵{A1,A2,…,An},其中Ai与Ai+1是可乘的,i=1,2…,n-1。

如何确定计算矩阵连乘积的计算次序,使得依此次序计算矩阵连乘积需要的数乘次数最少。

解答:我们按照动态规划的几个步骤来分析:(1)找出最优解的性质,刻画其特征结构对于矩阵连乘问题,最优解就是找到一种计算顺序,使得计算次数最少。

令m[i][j]表示第i个矩阵至第j个矩阵这段的最优解。

将矩阵连乘积简记为A[i:j] ,这里i<=j.假设这个最优解在第k处断开,i<=k<j,则A[i:j]是最优的,那么A[i,k]和A[k+1:j]也是相应矩阵连乘的最优解。

可以用反证法证明之。

这就是最优子结构,也是用动态规划法解题的重要特征之一。

(2)建立递归关系设计算A[i:j],1≤i≤j≤n,所需要的最少数乘次数m[i,j],则原问题的最优值为m[1,n] 。

当i=j时,A[i,j]=Ai, m[i,j]=0;(表示只有一个矩阵,如A1,没有和其他矩阵相乘,故乘的次数为0)当i<j时,m[i,j]=min{m[i,k]+m[k+1,j] +pi-1*pk*pj} ,其中i<=k<j(相当于对i~j这段,把它分成2段,看哪种分法乘的次数最少,如A1,A2,A3,A4,则有3种分法:{A1}{A2A3A4 }、{A1A2}{A3A4 }、{A1A2A3}{A4 },其中{}表示其内部是最优解,如{A1A2A3}表示是A1A2A3的最优解),也即:(3)计算最优值对于1≤i≤j≤n不同的有序对(i,j) 对于不同的子问题,因此不同子问题的个数最多只有o(n*n).但是若采用递归求解的话,许多子问题将被重复求解,所以子问题被重复求解,这也是适合用动态规划法解题的主要特征之一。

用动态规划算法解此问题,可依据其递归式以自底向上的方式进行计算。

在计算过程中,保存已解决的子问题答案。

每个子问题只计算一次,而在后面需要时只要简单查一下,从而避免大量的重复计算,最终得到多项式时间的算法。

动态规划――矩阵相乘

动态规划――矩阵相乘

动态规划――矩阵相乘一:问题描述有n个矩阵相乘,构造一个相乘次序,使得乘法的次数最低。

用程序写出求解每个子问题的结果。

二:算法设计与分析通过分析矩阵相乘,我们直到,其具有最优子结构,即一个最优解包含其子问题的最优解,而且有很多子问题是要重复计算的,所以我们可以用动态规划的算法自底向上的进行计算,保存子问题的答案,在后面的计算过程中就可以直接利用已经得到的答案,通过层层往上就可以得到原问题的结果。

三:源程序#include <stdio.h>#include <math.h>#include <iostream.h>#include <iomanip.h>#include <conio.h>#define MAX 32767 //定义一个最大值int a[11]; //存储在连乘时断开的位置.void find(int pos[11][11],int s,int e,int &i)//用递归算法求出断开的位置.{int b;b=pos[s][e];if(b<s)return ; //如果b的值小于s的,退出if(b>e)return ; //如果b的值大于s的,退出if(e==s+1)return ; //如果e只比s大一,退出a[i]=b;i++;find(pos,s,b,i);find(pos,b+1,e,i);}int main(){int N,p[11];int i,j,k,g;int temp[11][11],pos[11][11],temp1;printf("请输入相乘矩阵的个数(不大于10):");scanf("%d",&N); //总共有N个矩阵相乘printf("输入%d 个整数表示这%d 个矩阵的阶数:\n",N+1,N);for(i=0;i<=N;i++)scanf("%d",&p[i]); //这N个矩阵的阶数printf("\n计算得到的结果为如下所示:\n");for(i=1;i<=N;i++)temp[i][i]=0;for(g=2;g<=N;g++)for(i=1;i<=N-g+1;i++){j=i+g-1;temp[i][j]=MAX;for(k=i;k<=j-1;k++) //断点{temp1=temp[i][k]+temp[k+1][j]+p[i-1]*p[k]*p[j];if(temp1<temp[i][j]){temp[i][j]=temp1; //保存Ai..j相乘的最优值。

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

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

动态规划算法解矩阵连乘问题一、实验目的通过上机实验,要求掌握动态规划算法的问题描述、算法设计思想、程序设计和算法复杂性分析等。

二、实验环境VC6.0 C++,vs2005三、实验内容1 用动态规划算法解矩阵连乘问题(1)问题的描述给定n个矩阵{A1,A2,…,A n},其中A i与A i+1是可乘的,i=1,2,…,n-1。

要算出这n个矩阵的连乘积A1A2…A n。

由于矩阵乘法满足结合律,故计算矩阵的连乘积可以有许多不同的计算次序。

这种计算次序可以用加括号的方式来确定。

若一个矩阵连乘积的计算次序完全确定,也就是说该连乘积已完全加括号,则可以依此次序反复调用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。

动态规划之矩阵链相乘问题(算法导论)

动态规划之矩阵链相乘问题(算法导论)

动态规划之矩阵链相乘问题(算法导论)问题描述:给定n个矩阵序列,(A1,A2,A3,A4,...,An). 计算他们的乘积:A1A2A3...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次运算。

上⾯两种不同的运算顺序所有的计算量相差⼗倍。

因⽽,⼀种最优的计算顺序将能很⼤程度的减少矩阵连乘的运算量。

问题解析:此问题的⽬的是寻找⼀种最优的括号化⽅案。

下⾯⽤动态规划的思想来进⾏分析:1、动态规划的第⼀步:寻找最优⼦结构。

为⽅便起见,使⽤Ai..j表⽰AiAi+1...Aj的乘积结果矩阵。

对于k(i<=k<j), 计算Ai..j所需要的计算量为:Ai..k 和 Ak+1..j 以及⼆者相乘的代价和。

2、设m[i][j]为Ai..j的最优计算顺序所要花费的代价。

则其求解公式为:if i == j, m[i][j] = 0; //因为只有⼀个矩阵时计算代码为0,即不需要计算。

m[i][j]=min{m[i][k] + m[k+1][j] + Pi-1PkPj} i<=k<j3、为了能够输出求解顺序,需要保存区间中的⼀些分割点。

假如Ai..j中的最优分割点为k,则我们使⽤s[i][j]=k。

即在Ai..j 中,分别计算Ai..k 和 Ak+1..j 所⽤的计算开销最⼩。

4、采⽤⾃底向上的表格法。

依次求解矩阵长度为2,3,...,n的最优计算顺序。

算法思想:1、对m[i][i]全部初始化为0.2、在矩阵链A1..n中,依次计算长度len为2,3,...,n的m[i][j]⼤⼩。

C语言矩阵连乘(动态规划)详解

C语言矩阵连乘(动态规划)详解

C语⾔矩阵连乘(动态规划)详解动态规划法题⽬描述:给定n个矩阵{A1,A2....An},其中Ai与Ai+1是可以相乘的,判断这n个矩阵通过加括号的⽅式相乘,使得相乘的次数最少!以矩阵链ABCD为例按照矩阵链长度递增计算最优值矩阵链长度为1时,分别计算出矩阵链A、B、C、D的最优值矩阵链长度为2时,分别计算出矩阵链AB、BC、CD的最优值矩阵链长度为3时,分别计算出矩阵链ABC、BCD的最优值矩阵链长度为4时,计算出矩阵链ABCD的最优值动归⽅程:分析:k为矩阵链断开的位置d数组存放矩阵链计算的最优值,d[i][j]是以第i个矩阵为⾸,第j个矩阵为尾的矩阵链的最优值,i > 0m数组内存放矩阵链的⾏列信息,m[i-1]和m[i]分别为第i个矩阵的⾏和列(i = 1、2、3...)c语⾔实现代码:#include <stdio.h>#define N 20void MatrixChain(int p[N],int n,int m[N][N],int s[N][N]){int i,j,t,k;int r; //记录相乘的矩阵个数变量for(i=1;i<=n;i++){m[i][i]=0; //当⼀个矩阵相乘时,相乘次数为 0}//矩阵个数从两个开始⼀次递增for(r=2;r<=n;r++){//从某个矩阵开始for(i=1;i<=n-r+1;i++){//到某个矩阵的结束j=i+r-1;//拿到从 i 到 j 矩阵连乘的次数m[i][j]=m[i+1][j]+p[i-1]*p[i]*p[j];//拿到矩阵连乘断开的位置s[i][j]=i;//寻找加括号不同,矩阵连乘次数的最⼩值,修改 m 数组,和断开的位置 s 数组for(k=i+1;k<j;k++){t=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];if(t<m[i][j]){m[i][j]=t;s[i][j]=k;}}}}}int main(void){int n,n1,m1,i,j=2;int p[N]={0}; //存储矩阵的⾏和列数组int m[N][N]={0}; //存储矩阵与矩阵相乘的最⼩次数int s[N][N]={0}; //存储矩阵与矩阵相乘断开的位置printf("请输⼊矩阵个数:\n");scanf("%d",&n);for(i=1;i<=n;i++){printf("请输⼊第%d个矩阵的⾏和列(n1*m1 格式):",i);scanf("%d*%d",&n1,&m1);if(i==1){p[0]=n1;p[1]=m1;}else{p[j++]=m1;}}printf("\n记录矩阵⾏和列:\n");for(i=0;i<=n;i++){printf("%d ",p[i]);}printf("\n");MatrixChain(p,n,m,s);printf("\n矩阵相乘的最⼩次数矩阵为:\n");for(i=1;i<=n;i++){for(j=1;j<=n;j++){printf("%d ",m[i][j]);}printf("\n");}printf("\n矩阵相乘断开的位置矩阵为:\n");for(i=1;i<=n;i++){for(j=1;j<=n;j++){printf("%d ",s[i][j]);}printf("\n");}printf("矩阵最⼩相乘次数为:%d\n",m[1][n]);return 0;}感谢阅读,希望能帮助到⼤家,谢谢⼤家对本站的⽀持!。

n个矩阵连乘问题

n个矩阵连乘问题

矩阵连乘问题是一个经典的优化问题,其目标是在给定一组矩阵和它们之间的乘法顺序下,找出最少的括号方案数,使得乘法操作可以按照给定的顺序进行。

假设有n个矩阵A1, A2, ..., An,我们需要计算它们的连乘积。

每个矩阵Ai都有m×m的元素。

矩阵连乘问题可以转化为以下动态规划问题:
1. 定义dp[i][j]为计算矩阵Ai到Aj的连乘积所需的最少括号方案数。

2. 初始化dp[i][i]=0,表示单个矩阵不需要任何括号。

3. 对于i<j,计算dp[i][j]的递推关系:
dp[i][j] = dp[i][k] + dp[k+1][j] + p[i-1]*p[k]*p[j],其中k=i,...,j-1。

其中p是任意一个正整数,表示矩阵的维度m。

4. 最终答案为dp[1][n]。

以下是Python代码实现:
计算结果为:最少需要15个括号方案数。

矩阵连乘问题python

矩阵连乘问题python

矩阵连乘问题python矩阵连乘问题是一个经典的动态规划问题,我们可以使用动态规划来解决。

假设有n个矩阵需要连乘,其中第i个矩阵的维度为d[i-1] * d[i],其中d是一个长度为n+1的数组,表示矩阵的维度。

我们可以定义一个二维数组dp,其中dp[i][j]表示从第i个矩阵到第j个矩阵的最小乘法次数。

初始化dp数组,对于i=j的情况,dp[i][j]=0;对于i>j的情况,dp[i][j]=无穷大。

接下来,我们可以使用动态规划的思想来填充dp数组。

假设我们要计算dp[i][j],我们可以枚举中间的分割点k,将问题分解为两个子问题:从i到k的矩阵连乘和从k+1到j的矩阵连乘。

则dp[i][j]的值可以通过以下方式计算:dp[i][j] = min(dp[i][k] + dp[k+1][j] + d[i-1]*d[k]*d[j]) 最后,dp[1][n]即为所求的最小乘法次数。

以下是一个使用动态规划解决矩阵连乘问题的Python代码示例: ```pythondef matrix_chain_order(d):n = len(d) - 1dp = [[float("inf")] * (n+1) for _ in range(n+1)]for i in range(1, n+1):dp[i][i] = 0for l in range(2, n+1):for i in range(1, n-l+2):j = i + l -1for k in range(i, j):cost = dp[i][k] + dp[k+1][j] + d[i-1] * d[k] * d[j]if cost < dp[i][j]:dp[i][j] = costreturn dp[1][n]```使用示例:```pythond = [10, 20, 30, 40, 30]result = matrix_chain_order(d)print(result) # 输出:30000```以上代码中,d是一个长度为n+1的数组,表示n个矩阵的维度。

动态规划算法解矩阵连乘问题的源代码

动态规划算法解矩阵连乘问题的源代码
int n=sizeof(p)/sizeof(int)-1; //自动计算矩阵个数,增加程序灵活性
int i,j,k,r;
long **m=new long*[n+1]; int **s=new int*[n+1];
for(i=0;i<=n;i++) m[i]=new long[n+1]; //m行列数n*n,下标都从1开始
for(i=0;i<=n;i++)
{
if (i==0)
{
cout<<"\t";
}
else
{
cout<<i<<"\t";
}
}
cout<<endl;
for (i=1;i<=n;i++)
{
cout<<i<<"\t";
for (int j=1;j<=n;j++)
{
if (m[i][j]>=0)
{
cout<<m[i][j]<<"\t";
#include <iostream>
#include <conio.h>
#include <time.h>
using std::cout;
using std::endl;
int ma5,5,10,20,25}; //p[0],p[1]确定A1行列数,p[1],p[2]确定A2行列数,依次类推
{
j=i+r-1; /*相乘数组中最后数组的列指针*/

矩阵连乘问题(动态规划)

矩阵连乘问题(动态规划)

矩阵连乘问题(动态规划)一、实验目的与要求1、明确矩阵连乘的概念。

2、利用动态规划解决矩阵连乘问题。

二、实验题:问题描述:给定n个矩阵{A1,A2,...,An},其中Ai与Ai+1是可乘的,i=1,2...,n-1。

确定计算矩阵连乘积的计算次序,使得依此次序计算矩阵连乘积需要的数乘次数最少。

输入数据为矩阵个数和每个矩阵规模,输出结果为计算矩阵连乘积的计算次序和最少数乘次数。

三、实验代码#include<iostream>using namespace std;const int MAX = 100;//p用来记录矩阵的行列,main函数中有说明//m[i][j]用来记录第i个矩阵至第j个矩阵的最优解//s[][]用来记录从哪里断开的才可得到该最优解int p[MAX+1],m[MAX][MAX],s[MAX][MAX];int n;//矩阵个数int matrixChain(){for(int i=0;i<=n;i++)m[i][i]=0;for(int r=2;r<=n;r++)//对角线循环for(int i=0;i<=n-r;i++){//行循环int j = r+i-1;//列的控制//找m[i][j]的最小值,先初始化一下,令k=im[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(int k = i+1;k<j;k++){int temp=m[i][k]+m[k+1][j]+p[i]*p[k+1]*p[j+1];if(temp<m[i][j]){m[i][j]=temp;//s[][]用来记录在子序列i-j段中,在k位置处//断开能得到最优解s[i][j]=k;}}}return m[0][n-1];//最终结果}//根据s[][]记录的各个子段的最优解,将其输出void traceback(int i,int j){if(i==j){cout<<'A'<<i;return ;}if(i<s[i][j])cout<<'(';traceback(i,s[i][j]);if(i<s[i][j])cout<<')';if(s[i][j]+1<j)cout<<'(';traceback(s[i][j]+1,j);if(s[i][j]+1<j)cout<<')';}void traceback(){cout<<'(';traceback(0,n-1);cout<<')';cout<<endl;}int main(){cout<<"请输入矩阵的个数:"<<endl;cin>>n;cout<<"输入矩阵(形如a*b,中间用空格隔开):"<<endl;for(int i=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<<"输出结果如下:"<<endl;matrixChain();traceback(0,n-1);//最终解值为m[0][n-1];cout<<endl;return 0;}四、实验结果。

矩阵连乘问题(内附动态规划算法代码)

矩阵连乘问题(内附动态规划算法代码)

矩阵连乘问题(内附动态规划算法代码)矩阵连乘问题若矩阵A是⼀个p*q的矩阵,B是⼀个q*r的矩阵,则C=AB,是⼀个p*r的矩阵,需进⾏pqr次数乘计算。

存在{A1,A2,A3}三个矩阵,维数分别为100*5,5*50,50*10。

若直接相乘,A1*A2*A3,则需要进⾏n=100*5*50+100*50*10=25000+50000=75000次数乘计算。

如果我们调整运算顺序,A1*(A2*A3),则需要进⾏n=5*50*10+100*5*10=2500+5000=7500次数乘计算。

由此可见,当进⾏矩阵连乘运算时,加括号的⽅式,即计算次序对计算量有很⼤的影响。

代码展⽰:1 #include<iostream>23using namespace std;4/*5⾃底向上的推出矩阵连乘的最优解6先从两个矩阵相乘开始,⽽后三个矩阵相乘,四个......直到推出⽬标长度的最优解,即假设⼀个矩阵链,初始长度为2,算出所有相邻矩阵相乘的计算次数,⽽后使其长度为3...4...直到⽬标长度 7状态转移⽅程:8 m[i][j]=min {m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j]} i<=k<j i<j9 m[i][j]=0 i==j;10*/11#define LEN 5 //矩阵个数12//矩阵连乘函数,找到最优解13void MatrixChain(int *p, int m[][LEN + 1], int s[][LEN + 1]) {14for (int i = 0; i < LEN + 1; i++) m[i][i] = 0; //初始化,对⾓线元素置零,即当矩阵链长度为1时(只有⼀个矩阵)不⽤乘,为零15for (int r = 2; r <= LEN; r++) { //r表⽰矩阵链的长度,从2开始,两个矩阵相乘,⽽后3...4...5...16for (int i = 1; i <= LEN - r + 1; i++) { //i是矩阵链的⾸个矩阵,⼩于矩阵个数减矩阵链长度加⼀17int j = i + r - 1; //j是矩阵链的最后⼀个元素18 m[i][j] = m[i][i] + m[i + 1][j] + p[i - 1] * p[i] * p[j]; //m[i][j]是⼦结构,从最左边开始推19 s[i][j] = i; //标记断开的位置20for (int k = i + 1; k < j; k++) { //k是i和j直接的断开点,是在i和j之间的⼦结构,通过k的循环找到最优的解21int t = m[i][k] + m[k + 1][j] + p[i - 1] * p[k] * p[j]; //状态转移⽅程22if (t < m[i][j]) {23 m[i][j] = t; //更新最优解24 s[i][j] = k; //更新断开点25 }26 }27 }28 }29 }3031//回溯函数,根据s[i][j]数组标记的位置,回溯找到断开的位置32void Traceback(int i, int j, int s[][LEN + 1]) {33if (i == j) { //当i与j相等说明回溯到该矩阵的位置了34 cout << "A" << i;35 }36else {37 cout << "(";38 Traceback(i, s[i][j], s); //从尾往头回溯39 Traceback(s[i][j] + 1, j, s); //从断点往后回溯40 cout << ")";41 }42 }43//输出函数44void output(int t[][LEN + 1]) {45for (int i = 1; i <= LEN; i++) {46for (int j = 1; j <= LEN; j++) {47 cout << "" << t[i][j] << "";48 }49 cout << endl;50 }51 }52int main(void) {53int p[LEN + 1] = { 6,8,9,3,4,10 }; //矩阵的维度分别是2*3,3*4,4*5,5*6,6*7,LEN+1个数表⽰LEN个矩阵54int m[LEN + 1][LEN + 1] = { 0 }; //记录最优⼦结构的⼆维数组55int s[LEN + 1][LEN + 1] = { 0 }; //记录最优解对应的括号的位置5657 MatrixChain(p, m, s);5859 cout << endl;60 output(m);61 cout << endl;62 output(s);63 cout << endl;64 cout << "outcome:" <<endl;65 Traceback(1, LEN, s);66 cout << endl;6768return0;69 }运⾏结果:与备忘录⽅法的区别:我们使⽤的动态规划⽅法中其实融⼊了备忘录的⼀些东西,我们的m和s数组都是⽤来记录的,所以备忘录⽅法与我们使⽤的⽅法类似,不同在于,我们是⾃底向上的,⽽备忘录⽅法是⾃顶向下的进⾏。

动态规划实现矩阵链乘法问题

动态规划实现矩阵链乘法问题

动态规划实现矩阵链乘法问题矩阵链乘法问题( matrix-chain multiplication problem ) (1)问题描述 给定n个矩阵的链<A 1 ,A 2 ,…,A n >,其中i=1,2,…,n,矩阵A i的维数为p i-1 ×p i。

求⼀个完全“括号化⽅案”,使得计算乘积A 1 A 2 …A n 所需的标量乘法次数最⼩ (2)最优括号化⽅案的结构特征 ⽤记号 A i,j表⽰ A i A i+1 …A j通过加括号后得到的⼀个最优计算模式,且恰好在A k与A k+1之间分开。

则“前缀”⼦链A i A i+1 …A k必是⼀个最优的括号化⼦⽅案,记为A i,k;同理“后缀”⼦链A k+1 A k+2 …A j也必是⼀个最优的括号化⼦⽅案,记为A k+1,j。

(3)⼀个递归求解的⽅案 对于矩阵链乘法问题,我们将所有对于1≤i≤j≤n确定A i A i+1 …A j的最⼩代价括号⽅案作为⼦问题。

令m[i,j]表⽰计算矩阵A i,j所需要的标量乘法的次数最⼩值,则最优解就是计算A i...n所需的最低代价就是m[1,n] 递归定义m[i,j]。

①对于i=j的情况下,显然有m=0,不需要做任何标量乘法运算。

所以,对于所有的i=1、2......n,m[i,i] = 0. ②当i < j的情况,就按照最优括号化⽅案的结构特征进⾏计算m[i,j]。

假设最优括号化⽅案的分割点在矩阵A k和A k+1之间,那么m的值就是A i...k和A k+1...j的代价加上两者量程的代价的最⼩值。

即。

该公式的假设是最优分割点是已知的,但是实际上不知道。

然⽽,k只有j-i中情况取值。

由于最优分割点k必定在i~j内取得,只需要检查所有可能的情况,找到最优解即可。

可以得出⼀个递归公式 m只是给出了⼦问题最优解的代价,但是并未给出构造最优解的⾜够信息(即分割点的位置信息)。

所以,在此基础之上,我们使⽤⼀个⼆维数组s[i,j]来保存 A i A i+1 …A j 的分割点位置k。

动态规划解决矩阵连乘

动态规划解决矩阵连乘
s存放最优分割点k的值sij表示k是矩阵aiaj之间的最优分割点intij
#include<stdio.h> #define label 6 void matrix_mulitply(int a[],int m[][label],int s[][label],int n) { int i=0; int j=0; int k=0; int t=0; int l=0; for(i=0;i<n;i++) { m[i][i]=0; } for(t=1;t<n;t++) { for(l=1;l<=n-t;l++) { i=l; j=l+t; for(k=i;k<j;k++) { int min=m[i-1][k-1]+m[k][j-1]+a[i-1]*a[k]*a[j]; //以 K 将矩阵分为 A[1...k]和 A[k+1...j] if(min<m[i-1][j-1]||m[i-1][j-1]==-1) { m[i-1][j-1]=min; s[i-1][j-1]=k; } } } } } void output_result(int s[][label],int i,int j) { if(i==j) { printf("A%d",i); } //递归的输出最优的连乘次序 //以 K 分割后连乘代价是否更小,小则替换 //每轮 t+1 矩阵的可能组合,如 A1A2,A2A3,A3A4,A4A5 //一共进行 t 轮分析,每轮含 t+1 个矩阵连乘 //单个矩阵连乘代价为零
ห้องสมุดไป่ตู้
printf("输出原始 m[i][j]矩阵!\n"); for(j=0;j<label;j++) { for(i=0;i<=j;i++) { m[i][j]=-1; printf("%-10d",m[i][j]); } printf("\n"); } matrix_mulitply(a,m,s,label); printf("\n"); printf("输出计算后 m[i][j]矩阵!\n"); for(j=0;j<label;j++) { for(i=0;i<=j;i++) { printf("%-10d",m[i][j]); } printf("\n"); } printf("\n");

算法分析讲课大纲动态规划之求矩阵连乘积问题

算法分析讲课大纲动态规划之求矩阵连乘积问题

第一小节 动态规划问题——最短路径问题一 在正式提出动态规划法前我们先看一个数学例子:例1:在 x 1+x 2+x 3+…+x n =a 是约束条件下,求n x x x z +++= 21的极大值. 令 a x a f ==max )(1 ( 0a x ≤≤ ) )max())(max()(12x a x x a f x a f -+=-+= 令 x a x y -+=且0)(22121=---=--=x a x x x a xa xdxdy可得a x=x, 所以 x=a/2故 a a a a f 222)(2=+=同理 ))(2max()(max()(23x a x x a f x a f -+=-+=令 )(2x a x y -+=0)(222221=---=--=x a x x x a x a x dx dy 所以 a x=2x , x=a/3所以 f 3(a)=a a a a a f 331331231)(3==+=用数学归纳法可以证明:f n (a) =na , x 1=x 2=x 3=…=x n =na证明:1:n=1 …2:设f n (a) =na , x 1=x 2=x 3=…=x n =na成立,则 f n+1(a)=max(x +f n (a-x))=max()(x a n x -+)令 y=)(x a n x -+y ’=x 21xa n -2=0)(2=---x a x nx x a所以 nx=a-x ,(n+1)x=a x=1+n a f n+1(a)=1+n a +n 1+n a =a n )1(+ 我们刚才的解题策略是:“摸着石头过河”,f2 利用f1的结果,f3又利用f2的结果。

类似于游戏中的一个勇士打败了一些敌人后得到一件武器,然后去打败另一个强大一些的对手,得到一件更好的武器,接着打败更强大的敌人。

最后取得胜利。

在实际生活中,有这么一类问题,它们的活动过程可分为若干个阶段,而且在任一阶段 后的行为仅依赖于第I 阶段的过程状态,而与I 阶段之前的过程如何达到这种过程如何达到这种状态的方式无关,这样的过程就构成了一个多阶段决策过程。

0010算法笔记——【动态规划】矩阵连乘问题

0010算法笔记——【动态规划】矩阵连乘问题

问题描述:给定n个矩阵:A1,A2,...,A n,其中A i与A i+1是可乘的,i=1,2...,n-1。

确定计算矩阵连乘积的计算次序,使得依此次序计算矩阵连乘积需要的数乘次数最少。

输入数据为矩阵个数和每个矩阵规模,输出结果为计算矩阵连乘积的计算次序和最少数乘次数。

问题解析:由于矩阵乘法满足结合律,故计算矩阵的连乘积可以有许多不同的计算次序。

这种计算次序可以用加括号的方式来确定。

若一个矩阵连乘积的计算次序完全确定,也就是说该连乘积已完全加括号,则可以依此次序反复调用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)。

每一种完全加括号的方式对应于一个矩阵连乘积的计算次序,这决定着作乘积所需要的计算量。

看下面一个例子,计算三个矩阵连乘{A1,A2,A3};维数分别为10*100 , 100*5 , 5*50 按此顺序计算需要的次数((A1*A2)*A3):10X100X5+10X5X50=7500次,按此顺序计算需要的次数(A1*(A2*A3)):10*5*50+10*100*50=75000次所以问题是:如何确定运算顺序,可以使计算量达到最小化。

算法思路:例:设要计算矩阵连乘乘积A1A2A3A4A5A6,其中各矩阵的维数分别是:A1:30*35; A2:35*15; A3:15*5; A4:5*10; A5:10*20; A6:20*25递推关系:设计算A[i:j],1≤i≤j≤n,所需要的最少数乘次数m[i,j],则原问题的最优值为m[1,n]。

实现矩阵连乘的动态规划算法

实现矩阵连乘的动态规划算法

实现矩阵连乘的动态规划算法1.计算连个矩阵乘积的标准算法://标准算法void MatrixMultiply(int a[][MAXN], int b[][MAXN], int p, int q, int r){int sum[MAXN][MAXN];memset(sum, 0, sizeof(sum));int i, j, k;//遍历矩阵a的⾏for (k = 0; k < p; k++){//遍历矩阵b的列for (j = 0; j < r; j++){//对应位置相乘for (i = 0; i < q; i++){sum[k][j] += a[k][i] * b[i][j];}}}}所以A、B两个矩阵相乘的计算量为p*q*r。

2. 计算连个矩阵乘积的动态规划算法:#include<stdio.h>#include<stdlib.h>#include<Windows.h>#define MAX 100int matrix_chain(int *p, int n, int **m, int **s){//a[][]最⼩乘次数//s[][]最⼩乘数时的断开点int i,j,r,k;for (i = 0; i < n; i++) //单⼀矩阵的最⼩乘次都置为0{m[i][i] = 0;}for (r = 2; r <= n; r++) //r为连乘矩阵的个数{for (i = 0; i <= n-r; i++) //i表⽰连乘矩阵中的第⼀个{j = i + r -1; //j表⽰连乘矩阵中的最后⼀个m[i][j] = 99999;for (k = i; k <= j-1; k++) //在第⼀个与最后⼀个之间寻找最合适的断开点,注意,这是从i开始,即要先计算两个单独矩阵相乘的乘次{int tmp = m[i][k] + m[k+1][j] + p[i]*p[k+1]*p[j+1];if (tmp < m[i][j]){m[i][j] = tmp;s[i][j] = k;}}}}return m[0][n-1];}void print_chain(int i, int j, char **a,int **s){ //递归的⽅式来把最⼩乘数的表达式输出if (i == j){printf("%s",a[i]);}else{printf("(");print_chain(i,s[i][j],a,s);print_chain(s[i][j]+1,j,a,s);printf(")");}}int main(){//min_part[i][j]存储的是i+1到j+1的最⼩乘次,因为是从0开始//min_point[i][j]存储的是i+1到j+1之间最⼩乘次时的分割点int *p, **min_part, **min_point;char **a;int n = 6,i;int ret;p = (int *)malloc((n+1)*sizeof(int));a = (char **)malloc(n*sizeof(char*));min_part = (int **)malloc(n*sizeof(int *)); min_point = (int **)malloc(n*sizeof(int *));for (i = 0; i < n; i++){min_part[i] = (int *)malloc(n*sizeof(int)); min_point[i] = (int *)malloc(n*sizeof(int));a[i] = (char *)malloc(n*sizeof(char));}p[0] = 30; //第⼀个矩阵的⾏数p[1] = 35; //第⼆个矩阵的⾏数p[2] = 15; //……p[3] = 5; //……p[4] = 10; //……p[5] = 20; //第六个矩阵的⾏数p[6] = 25; //第六个矩阵的列数a[0] = "A1";a[1] = "A2";a[2] = "A3";a[3] = "A4";a[4] = "A5";a[5] = "A6";ret = matrix_chain(p,n,min_part,min_point); printf("Minest times:%d.\n",ret);print_chain(0,n-1,a,min_point);printf("\n");free(p);free(min_part);free(min_point);free(a);system("pause");return 0;}3.递归加括号的过程的运算量://加括号的过程是递归的。

【算法】【动态规划】矩阵连乘

【算法】【动态规划】矩阵连乘

首先看两个图。

矩阵相乘。

然后下面是矩阵相乘的代码。

/***只是矩阵的相乘。

*@author Administrator**/public class MatrixMultiply {public static void main(String args[]) {int a[][] = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } };int b[][] = { { 1, 5, 9 }, { 2, 6, 10 }, { 3, 7, 11 }, { 4,8, 12 } };int c[][] = new int[3][3];matrixMultiply(a, b, c, 3, 4, 4, 3);for (int i = 0; i <= 2; i++)for (int j = 0; j <= 2; j++)System.out.println(c[i][j]);}public static void matrixMultiply(int[][] a, int[][] b, int[][] c, int ra,int ca, int rb, int cb) {if (ca != rb) // 不能乘,a行不等于b列throw new IllegalArgumentException("矩阵不可乘");for (int i = 0; i < ra; i++)for (int j = 0; j < cb; j++) {int sum = a[i][0] * b[0][j];for (int k = 1; k < ca; k++)sum += a[i][k] * b[k][j];c[i][j] = sum;}}}动态规划的思想其实是把所有可能都记录起来,然后根据之前的去推后面的。

下面的代码中,用P来表示矩阵连乘的输入如P是{30,35,15,5,10,20} P有6个元素,却只有5个矩阵就代表30*35 35*15 15*5 5*10 10*20 5个矩阵数组M[i][j]代表从i乘到j这样需要的最少数乘数。

矩阵连乘问题c++代码

矩阵连乘问题c++代码

矩阵连乘问题c++代码以下是一个基于动态规划的C++代码解决矩阵连乘问题: cpp.#include <iostream>。

#include <climits>。

using namespace std;int matrixChainOrder(int p[], int n) {。

int m[n][n];int i, j, k, L, q;for (i = 1; i < n; i++)。

m[i][i] = 0;for (L = 2; L < n; L++) {。

for (i = 1; i < n L + 1; i++) {。

j = i + L 1;m[i][j] = INT_MAX;for (k = i; k <= j 1; k++) {。

q = m[i][k] + m[k + 1][j] + p[i 1] p[k] p[j];if (q < m[i][j])。

m[i][j] = q;}。

}。

}。

return m[1][n 1];}。

int main() {。

int arr[] = { 10, 20, 30, 40, 30 };int size = sizeof(arr) / sizeof(arr[0]);cout << "最小的乘法次数为," <<matrixChainOrder(arr, size) << endl;return 0;}。

这段代码使用了动态规划的思想来解决矩阵连乘问题。

首先,定义一个二维数组m来存储中间结果,其中m[i][j]表示从第i个矩阵乘到第j个矩阵所需的最小乘法次数。

然后,通过两层循环遍历所有可能的连乘长度,并计算出最小的乘法次数。

最后,返回m[1][n-1]作为结果,其中n为矩阵的个数。

在主函数中,我们定义了一个示例矩阵数组arr,并通过sizeof运算符计算出矩阵的个数。

动态规划实现矩阵连乘_C++

动态规划实现矩阵连乘_C++

#include<iostream.h>#include<math.h>#include <time.h>#include "windows.h"#define M 100#define N 50int cou=0;int v[M];struct Arry //存放一次相乘后的数组{int**a;};struct Arryt{int row;int cowl;int number;int**p;};int Common[N-1][N-1];void MartrixChain(int *p,int n,int **m,int**s){for(int i=1;i<=n;i++) m[i][i]=0;for(int r=2;r<=n;r++)for(int i=1;i<=n-r+1;i++){int j=i+r-1;m[i][j]=m[i][i]+m[i+1][j]+p[i-1]*p[i]*p[j];s[i][j]=i;for(int k=i+1;k<j;k++){int t=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];//选择最小的if (t<m[i][j]) {m[i][j]=t;s[i][j]=k;} //记录最优的断开位置}}}void Traceback(int i,int j,int **s)//返回一共记录的下个数{//s[i][j]记录了断开的位置,即计算A[i:j]的加括号方式为//(A[i:s[i][j]])*(A[s[i][j]+1:j])//int k=0;if(i==j)return ;Traceback(i,s[i][j],s);//递归打印A[i:s[i][j]]的加括号方式Traceback(s[i][j]+1,j,s);//递归打印A[s[i][j]+1:j]的加括号方式// cout<<"A"<<i<<"和A"<<(s[i][j]+1)<<"相乘"<<endl;cout<<"multiply A"<<i<<","<<s[i][j];cout<<"and A"<<(s[i][j]+1)<<","<<j<<endl;v[4*cou]=i; //记录乘法下标11,22,23等v[4*cou+1]=s[i][j];v[4*cou+2]=s[i][j]+1;v[4*cou+3]=j;cou=cou+1;// return k;}//----------------------------------------void selectMultiply(Arry *A,int v[],int c,int*p,Arryt *temp){int k;int s;int t;int m;int j,n,l,x,y;//k=c;// Arryt *temp=new Arryt[c];for(int i=0;i<c;i++){if(v[i*4]==v[i*4+1]){if(v[i*4+2]==v[i*4+3]){k=v[i*4]; //kk下标为11、22,33类型s=v[i*4+2]; //ss下标为11、22类型temp[i].p=new int*[p[k-1]];for(j=0;j<p[k-1];j++)temp[i].p[j]=new int[p[s]];temp[i].row=p[k-1];temp[i].cowl=p[s];temp[i].number=10*k+s;for(j=0;j<p[k-1];j++)for(n=0;n<p[s];n++){int sum=0;for(l=0;l<p[s-1];l++)sum=sum+A[k-1].a[j][l]*A[s-1].a[l][n];temp[i].p[j][n]=sum}}else{k=v[i*4]; //kk下标为11、22类型s=v[i*4+2]; //}//}st下标23、35类型t=v[i*4+3]; //}for(j=0;j<i;j++)if(temp[j].number=10*s+t) x=j;temp[i].p=new int*[p[k-1]];for(j=0;j<p[k-1];j++)temp[i].p[j]=new int[temp[x].cowl];temp[i].row=p[k-1];temp[i].cowl=temp[x].cowl;temp[i].number=10*k+t;for(j=0;j<p[k-1];j++)for(n=0;n<temp[x].cowl;n++){int sum=0;for(l=0;l<p[k];l++)sum=sum+A[k-1].a[j][l]*temp[x].p[l][n];temp[i].p[j][n]=sum;}}}else{if(v[i*4+2]==v[i*4+3]){k=v[i*4]; //}//}ks下标23、35类型s=v[i*4+1];//}t=v[i*4+2];//tt下标为11、22类型for(j=0;j<i;j++)if(temp[j].number=10*k+s) x=j;temp[i].p=new int*[temp[x].row];for(j=0;j<temp[x].row;j++)temp[i].p[j]=new int[p[t]];temp[i].row=temp[x].row;temp[i].cowl=p[t];temp[i].number=10*k+t;for(j=0;j<temp[x].row;j++)for(n=0;n<p[t];n++){int sum=0;for(l=0;l<temp[x].cowl;l++)sum=sum+temp[x].p[j][l]*A[t-1].a[l][n];temp[i].p[j][n]=sum;}}else{k=v[i*4]; //}ks下标23、35类型s=v[i*4+1];//}t=v[i*4+2];//tm下标23、35类型m=v[i*4+3];for(j=0;j<i;j++){if(temp[j].number=10*k+s) x=j;if(temp[j].number=10*t+m) y=j;}temp[i].p=new int*[temp[x].row];for(j=0;j<temp[x].row;j++)temp[i].p[j]=new int[temp[y].cowl];temp[i].row=temp[x].row;temp[i].cowl=temp[y].cowl;temp[i].number=10*k+m;for(j=0;j<temp[x].row;j++)for(n=0;n<temp[y].cowl;n++){int sum=0;for(l=0;l<temp[x].cowl;l++)sum=sum+temp[x].p[j][l]*temp[y].p[l][n];temp[i].p[j][n]=sum;}}}}}void outputselect(int c,int n,Arryt *temp){int i,j;int s=10+n;for(i=0;i<temp[c-1].row;i++){for(j=0;j<temp[c-1].cowl;j++)cout<<temp[c-1].p[i][j]<<" ";cout<<endl;}}void main(){int n,i,j;//连乘的数组的个数cout<<"输入连乘的数组的个数:";cin>>n;int *p;//维数int **m; //保存最优值数组int**s;//分配空间p=new int[n+1]; //分配矩阵维数数组空间cout<<"请输入第一个矩阵的行列数以及其他矩阵的列数:"<<endl;for (i=0;i<=n;i++)cin>>p[i];m=new int*[n+1]; //分配空间for(i=0;i<=n ; i++)m[i]=new int[n+1];s=new int*[n+1]; //分配空间for (i=0;i<=n ; i++)s[i]=new int[n+1];s=new int*[10]; //分配空间for (i=0;i<=10 ; i++)s[i]=new int[10];for(i=0;i<n;i++)cout<<"---矩阵A"<<i+1<<":"<<p[i]<<"x"<<p[i+1]<<endl;//给数组分配空间并且给数组随机赋值Arry *A=new Arry[n];for(i=0;i<n;i++){A[i].a=new int*[p[i]];for(j=0;j<p[i];j++)A[i].a[j]=new int[p[i+1]];for(int k=0;k<p[i];k++)for(j=0;j<p[i+1];j++){//srand(time(0));A[i].a[k][j]=rand()%6;}}MartrixChain(p,n,m,s);cout<<"\n----动态规划的路径"<<endl;Traceback(1,n,s);Arryt *temp=new Arryt[n];selectMultiply(A,v,cou,p,temp);cout<<"\n----输出最后的矩阵"<<endl;outputselect(cou,n,temp);for(i=0;i<n+1 ; i++) delete[] m[i];delete[] m; //释放二维数组空间delete[] p; //释放矩阵维数数组空间}。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
{
j=i+r-1; /*相乘数组中最后数组的列指针*/
m[i][j] = m[i+1][j]+ p[i-1]*p[i]*p[j]; /*得到两个数组相乘的运算量*/
s[i][j] = i;
for (k = i+1; k < j; k++) /*加括号方法得到的组数*/
{
long t = m[i][k] + m[k+1][j] + p[i-1]*p[k]*p[j]; /*得到每组运算量*/
动态规划算法解矩阵连乘问题的源代码
#include <iostream>
#include <conio.h>
#include <time.h>
using std::cout;
using std::endl;
int main()
{
int p[]={30,35,15,5,10,20,25}; //p[0],p[1]确定A1行列数,p[1],p[2]确定A2行列数,依次类推
int n=sizeof(p)/sizeof(int)-1; //自动计算矩阵个数,增加程序灵活性
int i,j,k,r;
long **m=new long*[n+1]; int **s=new int*[n+1];
for(i=0;i<=n;i++) m[i]=new long[n+1]; //m行列数n*n,下标都从1开始
for(i=0;i<=n;i++)
{
i;"\t";
}
else
{
cout<<i<<"\t";
}
}
cout<<endl;
for (i=1;i<=n;i++)
{
cout<<i<<"\t";
for (int j=1;j<=n;j++)
{
if (m[i][j]>=0)
{
cout<<m[i][j]<<"\t";
for (int j=1;j<=n;j++)
{
if (s[i][j]>=0)
{
cout<<s[i][j]<<"\t";
}
else
{
cout<<"\t";
}
}
cout<<endl;
}
return 0;
}
if (t < m[i][j])
{
m[i][j] = t; /*最小运算量*/
s[i][j] = k; /*括号分割的位置*/
}
}
}
//输出矩阵m与s的上三角阵,结果应与图(b)、(c)一致,你的代码写在下面!
//此处为你的输出矩阵m与s的上三角阵的代码!
cout<<"图(b)显示结果如下:"<<endl;
}
else
{
cout<<"\t";
}
}
cout<<endl;
}
cout<<"图(c)显示结果如下:"<<endl;
for(i=0;i<=n;i++)
{
if (i==0)
{
cout<<"\t";
}
else
{
cout<<i<<"\t";
}
}
cout<<endl;
for (i=1;i<=n;i++)
{
cout<<i<<"\t";
for(i=0;i<=n;i++) s[i]=new int[n+1]; //s行列数n*n,下标都从1开始
for(i=0;i<=n;i++) m[i][i]=s[i][i]=0; //矩阵初始化
//给以下程序加上注解
for (r = 2; r <= n; r++) /*数组相乘个数*/
for (i = 1; i <= n - r+1; i++) /* n行里每行要求得的值的个数*/
相关文档
最新文档