您的位置:首页 > 其它

动态规划之矩阵连乘

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]
;
}
  • 点赞
  • 收藏
  • 分享
  • 文章举报
Liquor___ 发布了30 篇原创文章 · 获赞 1 · 访问量 765 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: