算法设计 ||第10题:动态规划&矩阵连乘

已知有六个矩阵,其维数分别为

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; 
} 

源代码注释: 

  1. #include <stdio.h>:包含了标准输入输出的头文件。

  2. #define N 20:定义了一个常量N,表示矩阵的最大数量。

  3. 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]:存储矩阵与矩阵相乘断开的位置。
  4. int i,j,t,k;:定义了一些变量,用于循环和临时存储数据。

  5. int r; //相乘的矩阵个数变量:定义了一个变量r,表示相乘的矩阵个数。

  6. for(i=1;i<n;i++):循环遍历所有的矩阵。

    • 将1个矩阵相乘的次数设置为0,即m[i][i]=0。
  7. 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。

  8. int main(void):定义了主函数。

  9. int n,n1,m1,i,j=2;:定义了一些变量,用于接收用户输入和循环。

  10. int p[N]={0};:定义了一个数组p,用于存储矩阵的行和列。

  11. int m[N][N]={0};:定义了一个二维数组m,用于存储矩阵与矩阵相乘的最小次数。

  12. int s[N][N]={0};:定义了一个二维数组s,用于存储矩阵与矩阵相乘断开的位置。

  13. printf("请输入矩阵个数:\n");:输出提示信息,要求用户输入矩阵的数量。

  14. scanf("%d",&n);:接收用户输入的矩阵数量,并存储到变量n中。

  15. 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。
  16. printf("\n记录矩阵行和列:\n");:输出提示信息,表示开始记录矩阵的行和列。

  17. for(i=0;i<=n;i++):循环遍历所有的矩阵。

    • printf("%d ",p[i]);:输出数组p中的元素,即矩阵的行和列。
  18. MatrixChain(p,n,m,s);:调用MatrixChain函数计算矩阵相乘的最小次数和断开位置。

  19. printf("\n矩阵相乘的最小次数矩阵为:\n");:输出提示信息,表示矩阵相乘的最小次数矩阵。

  20. for(i=1;i<=n;i++):循环遍历所有的矩阵。

    • for(j=1;j<=n;j++):循环遍历所有的矩阵。

      • printf("%d ",m[i][j]);:输出二维数组m中的元素,即矩阵相乘的最小次数。
    • printf("\n");:换行。

  21. printf("\n矩阵相乘断开的位置矩阵为:\n");:输出提示信息,表示矩阵相乘断开的位置矩阵。

  22. for(i=1;i<=n;i++):循环遍历所有的矩阵。

    • for(j=1;j<=n;j++):循环遍历所有的矩阵。

      • printf("%d ",s[i][j]);:输出二维数组s中的元素,即矩阵相乘断开的位置。
    • printf("\n");:换行。

  23. printf("矩阵最小相乘次数为:%d\n",m[1][n]);:输出提示信息,表示矩阵的最小相乘次数。

  24. return 0;:返回0,表示程序正常结束。

运行结果: 

猜你喜欢

转载自blog.csdn.net/weixin_54570972/article/details/132580868