动态规划之矩阵连乘
2020-04-05 12:14
82 查看
动态规划之矩阵连乘
题目描述
给定n个矩阵{A1,A2,…,An},其中,Ai与Ai+1是可乘的,(i=1,2 ,…,n-1)。用加括号的方法表示矩阵连乘的次序,不同的计算次序计算量(乘法次数)是不同的,找出一种加括号的方法,使得矩阵连乘的次数最小。
这个题用一般的穷举法会很复杂,但是复杂度本人不太会算,反正就是麻烦就是了。所以想到动态规划,但是也不那么容易写出来。下面你尽量详细的给出解题思路。
动态转移方程:m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];
m[i][j]数组存放从i到j连乘的最少次数,相当于把1~n分成子问题,子问题最优解也是最优解。
R为子矩阵长度,即有几个。所以R从2开始最大为n。R为最外层循环。i每次从第一个开始,因为一共R个矩阵,所以i最大到n-R+1;然后内层循环为间断点k的位置,k可以括第一个 即k=i,但是k不可以全括住,因为没意义,所以k<n-R+1。然后刷新m[i][r]数组
m[i][i]=0,即只有一个的话为0次,这样相当于动规里的最后那个返回值(不知道说明白没)所以m[][]数组即可开始赋值刷新
举例
P0~5分别为 5 4 6 2 7
- 先赋值m[i][i]=0
- R=2,i从一开始,此时k只能取i的值。m[1][2]=min(m[1][1]+m[2][2]+p0p1p2)=120 同理进行
- R=3,i从一开始,k可以取i和i+1。m[1][3]=min(m[1][1]+m[2][3]+p0p1p3)此时用到了上一次循环的m[2][3].然后k=2;m[1][3]=min(m[1][2]+m[3][3]+p0p2p3) 在此次刷新m[1][3] 循环
大致思路既是如此,记得在开头把m数组赋最大值,否则第一次比较会出问题:memset(m,8,sizeof(m));这里声明,8不是阿拉伯数字8,而是代表一个很大的数,相当于赋最大值。可以试着在纸上写一下每次循环后的结果和上图对照。相信你会AC掉他。
#include<bits/stdc++.h> using namespace std; int p[100]; int m[100][100],s[100][100]; int n; void matrixchain() { memset(m,8,sizeof(m)); //赋最值 int i,r,j,k; for(int q=1;q<=n;q++) m[q][q]=0; //初始化 for(r=2;r<=n;r++) //外层循环为矩阵长度 { for(i=1;i<=n-r+1;i++) //循环每个数 最大只能到n-r+1,再往后矩阵长度不符合 { for(k=i;k<i+r-1;k++) //间断点位置 { m[i][i+r-1]=min(m[i][k]+m[k+1][i+r-1]+p[i-1]*p[k]*p[i+r-1],m[i][i+r-1]); } } } } int main() { cout<<"请输入矩阵的个数n : "<<endl; cin>>n; int i,j; cout<<"请依次输入每个矩阵的行数和最后一个矩阵的列数:"<<endl; for(i=0;i<=n;i++) cin>>p[i]; matrixchain(); cout<<m[1] ; }
补充一下怎么打印加括号的矩阵。加一个打印函数即可
#include<bits/stdc++.h> using namespace std; int p[100]; int m[100][100],s[100][100]; int n; void matrixchain() { memset(m,8,sizeof(m)); int i,r,j,k; for(int q=1;q<=n;q++) m[q][q]=0; for(r=2;r<=n;r++) { for(i=1;i<=n-r+1;i++) { s[i][i+r-1]=i; for(k=i;k<i+r-1;k++) { if(m[i][k]+m[k+1][i+r-1]+p[i-1]*p[k]*p[i+r-1]<m[i][i+r-1]) { m[i][i+r-1]=m[i][k]+m[k+1][i+r-1]+p[i-1]*p[k]*p[i+r-1]; s[i][i+r-1]=k; } } } } } void print(int i,int j) { if(i == j) { cout<<"A["<<i<<"]"; return; } cout<<"("; print(i,s[i][j]); print(s[i][j]+1,j); cout<<")"; } int main() { cout<<"请输入矩阵的个数n : "<<endl; cin>>n; int i,j; cout<<"请依次输入每个矩阵的行数和最后一个矩阵的列数:"<<endl; for(i=0;i<=n;i++) cin>>p[i]; matrixchain(); print(1,n); cout<<endl; cout<<m[1] ; }
- 点赞
- 收藏
- 分享
- 文章举报