矩阵连乘问题(递归与动态规划实现)

    技术2026-04-09  4

    问题描述

    给定n个矩阵{A1A2…An},其中Ai和Ai+1是可乘的,考察这n个矩阵的连乘积A1A2…An。由于矩阵的乘法满足结合律,故计算矩阵的连乘积有许多不同的计算次序,而不同的计算次序,所需要计算的连乘次数也是不同的,求解连乘次数最少的矩阵连乘最优次序。 **

    递归实现:

    #include "stdafx.h" int p[100],s[100][100],n; //计算最优值 int LookupChain(int i, int j,) { if (i == j) return 0; int u= LookupChain(i,i) + LookupChain(i+1,j) + p[i-1]*p[i]*p[j]; s[i][j] = i; for (int k = i+1; k < j; k++) { int t = LookupChain(i,k) + LookupChain(k+1,j) + p[i-1]*p[k]*p[j]; if (t < u) { u = t; s[i][j] = k;} } return u; } //构造最优解 void Traceback(int i, int j, int s[100][100]){ if(i==j) return; Traceback(i, s[i][j], s); Traceback(s[i][j]+1, j, s); printf("Multiply A%d,%d",i,s[i][j]); printf("and A%d,%d\n",s[i][j]+1,j); } int main(){ printf("请输入矩阵个数:\n"); scanf("%d",&n); printf("请输入矩阵各维数值:\n"); for(int i=0;i<n+1;i++){ scanf("%d",&p[i]); } printf("最优值为:%d\n",LookupChain(1,n)); printf("最优解为:\n"); Traceback(1,n,s); printf("\n"); return 0; }

    动态规划实现:

    #include "stdafx.h" //计算最优值 void matrixChain(int* p, int n,int m[100][100],int s[100][100]) { 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+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[100][100]){ if(i==j) return; Traceback(i, s[i][j], s); Traceback(s[i][j]+1, j, s); printf("Multiply A%d,%d",i,s[i][j]); printf("and A%d,%d\n",s[i][j]+1,j); } int main(int argc, char* argv[]) { int p[100],m[100][100],s[100][100]; int n; printf("请输入矩阵个数:\n"); scanf("%d",&n); printf("请输入矩阵各维数值:\n"); for(int i=0;i<n+1;i++){ scanf("%d",&p[i]); } matrixChain(p,n+1,m,s); printf("最优值为:%d\n",m[1][n]); printf("最优解为:\n"); Traceback(1,n,s); return 0; }

    测试

    测试递归程序: 测试过程:输入矩阵个数3,然后输入矩阵的行和列之后回车,系统输出最优值和最优解。

    测试动态规划程序: 测试过程:输入矩阵个数5,然后输入矩阵的行和列之后回车,系统输出最优值和最优解。

    讨论

    根据计算m[ i ][ j ]的递归式,容易写一个递归算法计算m[1][n]。但是简单地递归将耗费指数计算时间。在递归计算时,许多子问题被重复计算多次。这也是该问题可以用动态规划算法求解的又一显著特征。 用动态规划算法解决此问题,可依据其递归是以自底向上的方式进行计算。在计算的过程中,保存已解决的子问题答案。每个子问题只计算一次,而在后面需要时只要简单查一下,从而避免大量的重复计算。

    Processed: 0.009, SQL: 9