已知有六个矩阵,其维数分别为
r0=5, r1=10,r2=3,r3=12, r4=5, r5=50, r6= 6.
其中A1的维数是r0* r1。
用动态规划方法编程
输出六个矩阵最佳连乘次序和最少乘法次数。
(一)公式:
(二)源代码
#include <stdio.h>
#define N 20
void MatrixChain(int p[N],int n,int m[N][N],int s[N][N]){
int i,j,t,k;
int r; //相乘的矩阵个数变量
//1个矩阵相乘,相乘次数0
for(i=1;i<n;i++){
m[i][i]=0;
}
//2个开始
for(r=2;r<=n;r++){
for(i=1;i<=n-r+1;i++){
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++){
t= m[i][k]+ m[k+1][j]+p[i-1]*p[j]*p[k];
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;
}
源代码注释:
#include <stdio.h>
:包含了标准输入输出的头文件。
#define N 20
:定义了一个常量N,表示矩阵的最大数量。
void MatrixChain(int p[N],int n,int m[N][N],int s[N][N])
:定义了一个名为MatrixChain的函数,该函数用于计算矩阵相乘的最小次数和断开位置。参数:
p[N]
:存储矩阵的行和列数组。n
:矩阵的数量。m[N][N]
:存储矩阵与矩阵相乘的最小次数。s[N][N]
:存储矩阵与矩阵相乘断开的位置。
int i,j,t,k;
:定义了一些变量,用于循环和临时存储数据。
int r; //相乘的矩阵个数变量
:定义了一个变量r,表示相乘的矩阵个数。
for(i=1;i<n;i++)
:循环遍历所有的矩阵。
- 将1个矩阵相乘的次数设置为0,即m[i][i]=0。
for(r=2;r<=n;r++)
:循环遍历相乘的矩阵个数。
for(i=1;i<=n-r+1;i++)
:循环遍历所有可能的起始位置i。
j=i+r-1
:计算结束位置j。
m[i][j] = m[i+1][j]+p[i-1]*p[i]*p[j];
:计算从i到j相乘的最小次数,并存储到m[i][j]中。
s[i][j]=i;
:将断开位置设置为i。
for(k = i+1; k<j; k++)
:循环遍历i到j之间的所有可能的断开位置k。
t= m[i][k]+ m[k+1][j]+p[i-1]*p[j]*p[k];
:计算将矩阵链断开的方式下,两部分相乘的最小次数,并存储到t中。
if( t< m[i][j])
:如果t小于当前的最小次数m[i][j],
m[i][j]=t;
:更新最小次数为t。
s[i][j]=k;
:更新断开位置为k。
int main(void)
:定义了主函数。
int n,n1,m1,i,j=2;
:定义了一些变量,用于接收用户输入和循环。
int p[N]={0};
:定义了一个数组p,用于存储矩阵的行和列。
int m[N][N]={0};
:定义了一个二维数组m,用于存储矩阵与矩阵相乘的最小次数。
int s[N][N]={0};
:定义了一个二维数组s,用于存储矩阵与矩阵相乘断开的位置。
printf("请输入矩阵个数:\n");
:输出提示信息,要求用户输入矩阵的数量。
scanf("%d",&n);
:接收用户输入的矩阵数量,并存储到变量n中。
for(i=1;i<=n;i++)
:循环遍历所有的矩阵。
printf("请输入第%d个矩阵的行和列(n1*m1 格式):",i);
:输出提示信息,要求用户输入第i个矩阵的行和列。
scanf("%d*%d",&n1,&m1);
:接收用户输入的行和列,并分别存储到变量n1和m1中。
if(i==1)
:如果是第1个矩阵,
p[0]=n1;
:将第一个矩阵的行数存储到数组p的第一个元素。
p[1]=m1;
:将第一个矩阵的列数存储到数组p的第二个元素。
else
:如果不是第1个矩阵,
p[j++]=m1;
:将矩阵的列数存储到数组p的第j个元素,并将j增加1。
printf("\n记录矩阵行和列:\n");
:输出提示信息,表示开始记录矩阵的行和列。
for(i=0;i<=n;i++)
:循环遍历所有的矩阵。
printf("%d ",p[i]);
:输出数组p中的元素,即矩阵的行和列。
MatrixChain(p,n,m,s);
:调用MatrixChain函数计算矩阵相乘的最小次数和断开位置。
printf("\n矩阵相乘的最小次数矩阵为:\n");
:输出提示信息,表示矩阵相乘的最小次数矩阵。
for(i=1;i<=n;i++)
:循环遍历所有的矩阵。
for(j=1;j<=n;j++)
:循环遍历所有的矩阵。
printf("%d ",m[i][j]);
:输出二维数组m中的元素,即矩阵相乘的最小次数。
printf("\n");
:换行。
printf("\n矩阵相乘断开的位置矩阵为:\n");
:输出提示信息,表示矩阵相乘断开的位置矩阵。
for(i=1;i<=n;i++)
:循环遍历所有的矩阵。
for(j=1;j<=n;j++)
:循环遍历所有的矩阵。
printf("%d ",s[i][j]);
:输出二维数组s中的元素,即矩阵相乘断开的位置。
printf("\n");
:换行。
printf("矩阵最小相乘次数为:%d\n",m[1][n]);
:输出提示信息,表示矩阵的最小相乘次数。
return 0;
:返回0,表示程序正常结束。